質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

地図上に円を書きたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 181

harapecco

score 0

前提・実現したいこと

ジオフェンスエリアの可視化のために
手に入れた緯度経度を中心とした半径100の円を地図上に表示したいです。
Pinの表示はできるのに、サークルの表示はできません。
参考サイトにあるようにマップを再作成するとできますが、すでにマップを作成しているためそちらにサークルをいれこみたいです。
参考にしたサイトhttps://sites.google.com/a/gclue.jp/swift-docs/ni-yinki100-ios/7-mapkit/de-tu-shangni-tu-xingwo-miaoku-yuan

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

`` swift5

import UIKit
import CoreLocation
import MapKit

class ViewController: UIViewController, UITextFieldDelegate ,UIPickerViewDelegate, UIPickerViewDataSource ,MKMapViewDelegate{

    override func viewDidLoad() {
        super.viewDidLoad()
         //Do any additional setup after loading the view.

        //timerSettingPickerのデリゲートとソースの先を決定
        timerSettingPicker.delegate = self
        timerSettingPicker.dataSource = self

        //Texデリゲート先決定
        inputText.delegate = self
        //UserDefaultの取得
        let settings = UserDefaults.standard
        settings.register(defaults: [settingKey:1])
        let timerValue = settings.integer(forKey: settingKey)

        //Pickerの設定
        for row in 0..<settingArray.count{
            if settingArray[row] == timerValue{
                timerSettingPicker.selectRow(row, inComponent: 0, animated: true)
            }
        }

        // ロケーションマネージャのセットアップ
        setupLocationManager()
        // 地図の初期化
        initMap()
    }

    @IBOutlet weak var inputText: UITextField!
    @IBOutlet weak var timerSettingPicker: UIPickerView!
    @IBOutlet weak var Latitude: UILabel!
    @IBOutlet weak var Longtude: UILabel!
    @IBOutlet weak var latitudeNOW: UILabel!
    @IBOutlet weak var longtudeNOW: UILabel!
    @IBOutlet weak var frequencytime: UILabel!
    @IBOutlet weak var time: UILabel!
    @IBOutlet weak var Geoarea: UILabel!
    @IBOutlet weak var Geostatus: UILabel!
    @IBOutlet weak var circle: UILabel!

    //検索位置の中心を決める
    var center: CLLocationCoordinate2D!
    //更新回数
    var freqtime = 0
    //タイマー
    var timer : Timer?
    //カウント変数
    var count = 0
    //更新頻度の数字の配列作成
    let settingArray : [Int] = [0,1,2,3,4,5,10,20,30,60]
    //記憶しておく
    let settingKey = "timer_value"
    // 緯度
    var latitudeNow: String = ""
    // 経度
    var longitudeNow: String = ""
    /// ロケーションマネージャ
    var locationManager: CLLocationManager!

    @IBAction func Getstart(_ sender: Any) {
       // マネージャの設定
        let status = CLLocationManager.authorizationStatus()
        if status == .denied {
            showAlert()
        }else{
            if let nowTimer = timer{
                //処理なし
                if nowTimer.isValid == true{
            return
                }
            }

            //時間ごとに動作を実行
            timer = Timer.scheduledTimer(timeInterval: 1.0,
                                                          target: self,
                                                          selector: #selector(self.timerInterrupt(_:)),
                                                          userInfo: nil,
                                                          repeats: true)
            }
    }

    @IBAction func Getstop(_ sender: Any) {
        self.latitudeNOW.text = "いど"
        self.longtudeNOW.text = "けいど"
        timer?.invalidate()
        self.Geostatus.text = "モニタリング終了"

    }

    func countdown() -> Int{
        let settings = UserDefaults.standard
        let timerValue = settings.integer(forKey: settingKey)
        let remainCount = timerValue - count
        return remainCount
    }

    //経過時間毎の処理
    @objc func timerInterrupt(_ timer: Timer ){
        count += 1
        if countdown() <= 0 {
             //位置情報の更新
            self.latitudeNOW.text = self.latitudeNow
             self.longtudeNOW.text = self.longitudeNow
             NSLog(self.latitudeNow+self.longitudeNow);
            freqtime += 1
            print(freqtime)
            self.time.text = String(freqtime)
            count = 0
        }
    }

    @IBAction func OutPutLog(_ sender: Any) {
        freqtime = 0
        self.time.text = String(freqtime)
    }
    @IBOutlet weak var Map: MKMapView!

/// ロケーションマネージャのセットアップ
func setupLocationManager() {
    locationManager = CLLocationManager()

    // 権限をリクエスト
    guard let locationManager = locationManager else { return }
    locationManager.requestAlwaysAuthorization()


    // マネージャの設定
    let status = CLLocationManager.authorizationStatus()

    // ステータスごとの処理
    if status == .authorizedWhenInUse {
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
    }
}

/// アラートを表示する
func showAlert() {
    let alertTitle = "位置情報取得が許可されていません。"
    let alertMessage = "設定アプリの「プライバシー > 位置情報サービス」から変更してください。"
    let alert: UIAlertController = UIAlertController(
        title: alertTitle,
        message: alertMessage,
        preferredStyle:  UIAlertController.Style.alert
    )
    // OKボタン
    let defaultAction: UIAlertAction = UIAlertAction(
        title: "OK",
        style: UIAlertAction.Style.default,
        handler: nil
    )
    // UIAlertController に Action を追加
    alert.addAction(defaultAction)
    // Alertを表示
    present(alert, animated: true, completion: nil)
}

    //現在地の更新
    func initMap() {
        let Map: MKMapView = MKMapView()
        // 縮尺を設定
        var region:MKCoordinateRegion = Map.region
        region.span.latitudeDelta = 0.001
        region.span.longitudeDelta = 0.001
        Map.setRegion(region,animated:true)

        // 現在位置表示の有効化
        Map.showsUserLocation = true
        // 現在位置設定(デバイスの動きとしてこの時の一回だけ中心位置が現在位置で更新される)
        Map.userTrackingMode = .follow
    }

    func updateCurrentPos(_ coordinate:CLLocationCoordinate2D) {
        var region:MKCoordinateRegion = Map.region
        region.center = coordinate
        Map.setRegion(region,animated:true)
    }

    //UIPickerの列の数
        func numberOfComponents(in pickerView: UIPickerView) -> Int{
            return 1
        }
    //UIPikedrの行の数
        func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent componemt: Int) -> Int{
            return settingArray.count
        }

    //UIPickerに表示する内容を設定
        func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
            return String(settingArray[row])
        }

    //Pickerがいじられたときのデータの格納
        func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
            let settings = UserDefaults.standard
            settings.setValue(settingArray[row], forKey: settingKey)
            settings.synchronize()
        }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        //キーボード を閉じる
        textField.resignFirstResponder()

        //入力された文字を取り出す
        if let searchKey = textField.text{
            print(searchKey)
            //CLgeocodeをゲット
            let geocoder = CLGeocoder()
            geocoder.geocodeAddressString(searchKey, completionHandler: {(placemarks , error) in
            //入力情報から位置情報を取得
            if let unwrapPlacemarks = placemarks{
                if let firstPlacemark = unwrapPlacemarks.first{
                if let location = firstPlacemark.location{
                    let targetCoordinate = location.coordinate
                    print(targetCoordinate)

                    self.center = targetCoordinate

                    //ピン生成
                    let pin = MKPointAnnotation()
                    pin.coordinate = targetCoordinate
                    pin.title = searchKey
                    self.Map.addAnnotation(pin)

                    // viewにmapViewを追加.
                    self.view.addSubview(self.Map)
                    // 半径100の円をかく
                    let myCircle: MKCircle = MKCircle(center: self.center, radius: CLLocationDistance(100))
                    // mapViewにcircleを追加.
                    self.Map.addOverlay(myCircle)

                    //モニタリングのやつ
                        // モニタリングしたい場所の緯度経度を設定
                        let moniteringCordinate = targetCoordinate
                        // モニタリングしたい領域を作成
                        let moniteringRegion = CLCircularRegion.init(center: moniteringCordinate, radius: 100.0, identifier: searchKey)
                        // モニタリング開始
                        self.locationManager.startMonitoring(for: moniteringRegion)

                        self.circle.text = "100m"

                        }
                    }
                }
            })
        }
        return true
        }
    //円を書く
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        // rendererを生成.
        let myCircleView: MKCircleRenderer = MKCircleRenderer(overlay: overlay)
        // 円の内部を赤色で塗りつぶす.
        myCircleView.fillColor = UIColor.red
        // 円周の線の色を黒色に設定.
        myCircleView.strokeColor = UIColor.black
        // 円を透過させる.
        myCircleView.alpha = 0.5
        // 円周の線の太さ.
        myCircleView.lineWidth = 1.5
        return myCircleView
    }

```

試したこと

参考サイトのように地図を生成してあげるとうまくいったので、
overrayの部分が、うまくマップに取り込めていないせいで、サークルの設定がうまくいってないように感じています。

補足情報(FW/ツールのバージョンなど)

swift5
xcode11.5

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • TsukubaDepot

    2020/07/05 22:05

    まだ確かめていないので、コードを見た感想ですが、参考にされたサイトでいうところの

    myMapView.delegate = self

    に相当する記述がありませんが、別途おこなっているのでしょうか。
    また、

    func initMap() {
    let Map: MKMapView = MKMapView()

    のところでトップレベルのスコープにある Map と同じ名前で違う実体の変数を用意し、使っていますが、それで問題ないのでしょうか。

    キャンセル

  • harapecco

    2020/07/05 22:47

    おお!
    ありがとうございます。
    delegate ミスでした。
    渡してあげたらしっかり作動しました!

    キャンセル

  • TsukubaDepot

    2020/07/06 06:07

    それはよかったです。
    ただ、このままでは未解決のまま残ってしまいますので、よかったら自己解決という形でこの質問を閉じていただけないでしょうか(未解決と思ってみる方もいるので)。

    キャンセル

回答 1

check解決した方法

0

delegateの設定ミス

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る