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

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

ただいまの
回答率

88.80%

MKMapViewとLong Press Gesture Recognizerを使用して経路が検索できる地図アプリを作る

受付中

回答 0

投稿 編集

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

shisen-t

score 21

MKMapViewを用いて地図アプリを製作しようと考えています。
またMap上を長押しするとピンが刺さり現在地からピンまでの経路を示すようにしたいと考えています。
下記のコードを書いたところビルドは成功して動作中にエラーが出る事もないのですが、長押しをしてもピンが刺さらず経路を示すことができませんでした。
Long Press Gesture Recognizerをもう一度MapView上に配置し直したり、コードを確認したりしたのですが解決方法がわからず質問させていただいた次第です。

コンソールには
[Warning] WARNING: A Gesture recognizer (<UILongPressGestureRecognizer: 0x10090b670; state = Possible; view = <MKMapView 0x101028400>; target= <(action=pressMap:, target=<test.ViewController 0x10090b9e0>)>>) was setup in a storyboard/xib to be added to more than one view (-><MKMapView: 0x101028400; frame = (0 20; 375 556); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x280db0cf0>; layer = <CALayer: 0x28030d0a0>>) at a time, this was never allowed, and is now enforced. Beginning with iOS 9.0 it will be put in the first view it is loaded into.
と表示されているため、Long Pressに問題があるものと考えています。

どなたかお分かりになる方がいらっしゃいましたら、お力添えいただけますと幸いです。

コード
import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var testMapView: MKMapView!

    var testManager: CLLocationManager = CLLocationManager()


    @IBAction func pressMap(_ sender: UILongPressGestureRecognizer) {
        //長押しタップした位置を取得
        let location: CGPoint = sender.location(in: testMapView)

        if (sender.state == UIGestureRecognizer.State.ended){
            //タップした位置を緯度経度の座標に変換
            let mapPoint: CLLocationCoordinate2D = testMapView.convert(location, toCoordinateFrom: testMapView)

            //ピンを生成
            let annotation: MKPointAnnotation = MKPointAnnotation()
            //座標を設定
            annotation.coordinate = mapPoint
            //タイトルを設定
            annotation.title = "目的地"
            //サブタイトルを設定
            annotation.subtitle = "ボタンタップで経路を表示"
            // MapViewにピンを追加
            testMapView.addAnnotation(annotation)
        }
    }

    func mapView(mapView: MKMapView, viewFor annotation: MKPointAnnotation) -> MKAnnotationView? {


        let annotationIdentifier = "annotationIdentifier"
        //ピンを生成
        let testView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
        //コールアウト(吹き出し)を表示する
        testView.canShowCallout = true
        //アニメーションをつける
        testView.animatesDrop = true
        // annotationを設定
        testView.annotation = annotation

        //annotationViewに経路ボタンを追加
        let button = UIButton()
        button.frame = CGRect(x: 0,y: 0,width: 40,height: 30)
        button.setTitle("経路", for: .normal)
        button.backgroundColor = UIColor.blue
        button.setTitleColor(UIColor.white, for: .highlighted)
        testView.rightCalloutAccessoryView = button

        return testView

    }

    //経路ボタンが押されたとき
    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        //目的地の位置情報を作る
        let coordinate = CLLocationCoordinate2DMake(view.annotation!.coordinate.latitude, view.annotation!.coordinate.latitude)
        let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: nil)
        let mapItem = MKMapItem(placemark: placemark)

        //起動オプション
        let option: [String:AnyObject] = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving as AnyObject, MKLaunchOptionsMapTypeKey: MKMapType.hybrid.rawValue as AnyObject]

        //マップアプリを起動
        mapItem.openInMaps(launchOptions: option)

    }







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

        //デリゲート先を自分に設定する。
        testManager.delegate = self

        //位置情報の利用許可を変更する画面をポップアップ表示する。
        testManager.requestWhenInUseAuthorization()

        //位置情報の取得を要求する。
        testManager.requestLocation()
    }



    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }



}



extension ViewController: CLLocationManagerDelegate {
    //位置情報取得時の呼び出しメソッド
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){

        for location in locations {
            //現在位置をマップの中心にして登録する。
            let center = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
            let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05) //
            let region = MKCoordinateRegion(center: center, span: span)
            testMapView.setRegion(region, animated:true)
        }
    }



    //位置情報取得失敗時の呼び出しメソッド
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正の依頼

  • t_obara

    2019/04/04 19:38

    Long Pressが認識されないのか、ピンを置くことができないのかは切り分けできているのですか?

    キャンセル

まだ回答がついていません

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

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

関連した質問

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