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

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

ただいまの
回答率

90.99%

  • Swift

    6097questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    3517questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)と表示されアプリがクラッシュされてしまいます。

解決済

回答 1

投稿 編集

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

madotuki

score 2

前提・実現したいこと

Swift初学者です。
SwiftとMapKitを用いて現在地と目的地の経路を結ぶプログラムを作成しています。その際、経路取得の関数で
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
というメッセージが出てしまい、コンパイルはできるものの、アプリがクラッシュしてしまいます。

該当のソースコード

 func getRoute()
    {
        // 現在地と目的地のMKPlacemarkを生成
        var fromPlacemark = MKPlacemark(coordinate:userLocation, addressDictionary:nil)
        var toPlacemark   = MKPlacemark(coordinate:destLocation, addressDictionary:nil)

        // MKPlacemark から MKMapItem を生成
        var fromItem = MKMapItem(placemark:fromPlacemark)
        var toItem   = MKMapItem(placemark:toPlacemark)

        // MKMapItem をセットして MKDirectionsRequest を生成
        let myRequest: MKDirectionsRequest = MKDirectionsRequest()


        myRequest.source = fromItem
        myRequest.destination = toItem
        myRequest.requestsAlternateRoutes = true
        myRequest.transportType = MKDirectionsTransportType.any

        let directions = MKDirections(request:myRequest)
        directions.calculate(completionHandler: {
            (response:MKDirectionsResponse!, error:NSError!) -> Void in

            _ = response.routes.count
            if (error != nil || response.routes.isEmpty) {
                return
            }
            var route: MKRoute = response.routes[0] as MKRoute
            // 経路を描画
            self.myMap.add(route.polyline)
            } as! MKDirectionsHandler)
           //↑ここでエラーメッセージ
        func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        let route: MKPolyline = overlay as! MKPolyline
        let routeRenderer = MKPolylineRenderer(polyline:route)
        routeRenderer.lineWidth = 5.0
        routeRenderer.strokeColor = UIColor.red
        return routeRenderer
        }
    }

試したこと

response.routes.countのところでワーニングが出ていたので戻り値を使用しないことを明確にするよう _ = をつけました。
またOutlet接続もできていることを確認しました。

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

swift4
xcode9

一応コード全容を記述します。

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController,MKMapViewDelegate, CLLocationManagerDelegate {

//    目的地
    var destLocation = CLLocationCoordinate2D(latitude: 35.658611, longitude: 139.745556)

//    現在地
    var userLocation: CLLocationCoordinate2D!


    // マップビュー
    @IBOutlet weak var myMap: MKMapView!
    // ツールバー
    @IBOutlet weak var toolBar: UIToolbar!
    // ツールバーのTintColorの初期値
    var defaultColor:UIColor!

    var locationManager = CLLocationManager()

    @IBOutlet weak var trackingButton: UIBarButtonItem!

    // 地図のタイプを切り替える
    @IBAction func changedMapType(_ sender: UISegmentedControl) {
        switch sender.selectedSegmentIndex {
        case 0 :
            // 地図
            myMap.mapType = .standard
            // 俯角(見下ろす角度)
            myMap.camera.pitch = 0.0
            // ツールバーを標準に戻す
            toolBar.tintColor = defaultColor
            toolBar.alpha = 1.0
        case 1 :
            // 衛星写真
            myMap.mapType = .satellite
            // ツールバーを黒文字、背景半透明にする
            toolBar.tintColor = UIColor.black
            toolBar.alpha = 0.8
        case 2 :
            // 写真+地図(ハイブリッド)
            myMap.mapType = .hybrid
            // ツールバーを黒文字、背景半透明にする
            toolBar.tintColor = UIColor.black
            toolBar.alpha = 0.8
        case 3:
            // 地図
            myMap.mapType = .standard
            // ツールバーを標準に戻す
            toolBar.tintColor = defaultColor
            toolBar.alpha = 1.0
            // 3Dビュー
            myMap.camera.pitch = 70 // 俯角(見下ろす角度)
            myMap.camera.altitude = 700 // 標高
        default:
            break
        }
    }

    // トラッキングモードを切り替える
    @IBAction func tapTrackingButton(_ sender: UIBarButtonItem) {
        getRoute()
        switch myMap.userTrackingMode {
        case .none:
            // noneからfollowへ
            myMap.setUserTrackingMode(.follow, animated: true)
            // トラッキングボタンを変更する
            trackingButton.image = UIImage(named: "trackingFollow")
        case .follow:
            // followからfollowWithHeadingへ
            myMap.setUserTrackingMode(.followWithHeading, animated: true)
            // トラッキングボタンを変更する
            trackingButton.image = UIImage(named: "trackingHeading")
        case .followWithHeading:
            // followWithHeadingからnoneへ
            myMap.setUserTrackingMode(.none, animated: true)
            // トラッキングボタンを変更する
            trackingButton.image = UIImage(named: "trackingNone")
        }
    }

    // トラッキングが自動解除された
    func mapView(_ mapView: MKMapView, didChange mode: MKUserTrackingMode, animated: Bool) {
        // トラッキングボタンを変更する
        trackingButton.image = UIImage(named: "trackingNone")
    }

    // 位置情報利用許可のステータスが変わった
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

        userLocation = CLLocationCoordinate2DMake(manager.location!.coordinate.latitude, manager.location!.coordinate.longitude)

        // 現在地の取得を開始
        self.locationManager.startUpdatingLocation()


        switch status {
        case .authorizedAlways, .authorizedWhenInUse :
            // ロケーションの更新を開始
            locationManager.startUpdatingLocation()
            // トラッキングボタンを有効
            trackingButton.isEnabled = true
        default:
            // ロケーションの更新を停止
            locationManager.stopUpdatingLocation()
            // トラッキングモードをnoneに
            myMap.setUserTrackingMode(.none, animated: true)
            //トラッキングボタンを変更
            trackingButton.image = UIImage(named: "trackingNone")
            // トラッキングボタンを無効にする
            trackingButton.isEnabled = false
        }
    }




    override func viewDidLoad() {
        super.viewDidLoad()
        // スケールを表示する
        myMap.showsScale = true

    locationManager.requestWhenInUseAuthorization()

        locationManager.delegate = self

        myMap.delegate = self


    }

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



    func getRoute()
    {
        // 現在地と目的地のMKPlacemarkを生成
        var fromPlacemark = MKPlacemark(coordinate:userLocation, addressDictionary:nil)
        var toPlacemark   = MKPlacemark(coordinate:destLocation, addressDictionary:nil)

        // MKPlacemark から MKMapItem を生成
        var fromItem = MKMapItem(placemark:fromPlacemark)
        var toItem   = MKMapItem(placemark:toPlacemark)

        // MKMapItem をセットして MKDirectionsRequest を生成
        let myRequest: MKDirectionsRequest = MKDirectionsRequest()


        myRequest.source = fromItem
        myRequest.destination = toItem
        myRequest.requestsAlternateRoutes = true
        myRequest.transportType = MKDirectionsTransportType.any

        let directions = MKDirections(request:myRequest)
        directions.calculate(completionHandler: {
            (response:MKDirectionsResponse!, error:NSError!) -> Void in

            _ = response.routes.count
            if (error != nil || response.routes.isEmpty) {
                return
            }
            var route: MKRoute = response.routes[0] as MKRoute
            // 経路を描画
            self.myMap.add(route.polyline)
            } as! MKDirectionsHandler)

        func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        let route: MKPolyline = overlay as! MKPolyline
        let routeRenderer = MKPolylineRenderer(polyline:route)
        routeRenderer.lineWidth = 5.0
        routeRenderer.strokeColor = UIColor.red
        return routeRenderer
        }
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

該当のエラー箇所を次のように修正したらうまくいかないでしょうか?

let directions = MKDirections(request: myRequest)
directions.calculate(completionHandler: {(response, error) -> Void in
    _ = response!.routes.count
    if (error != nil || response!.routes.isEmpty) {
        return
    }
    var route: MKRoute = response!.routes[0] as MKRoute
    // 経路を描画
    self.myMap.add(route.polyline)
}

エラーになっていた原因は、 as! MKDirectionsHandler にあると思います。
(response:MKDirectionsResponse!, error:NSError!) -> Void in の書き方だと handler の型に反ってないため実行時エラーが起きているようです。
おそらく Xcode のエラーででてくる補完を利用したと思うのですが、あれはあまりアテにしてはいけません。

また、 MKDirectionsHandler は directions.calculate { response, error in のようにもアクセスできますので、一般的にはこう書きます。
この書き方は Trailing Closure というのですが、最初のうちは深く考えずにこういう風に書ける記法があると思えば問題ないと思います。 \[Swift\] Closureについてメモ \- Qiita 


本筋とは関係ないですが、 response!.routes.isEmpty の ! でエラーになる可能性がありますので以下のように ! を使わずに書くほうが良いです。

if error == nil {
    return
}
guard let response = response else {
    return
}
if response.routes.ieEmpty {
    return
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • Swift

    6097questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    3517questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。