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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode

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

Swift

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

Q&A

解決済

1回答

7967閲覧

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

madotuki

総合スコア8

Xcode

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

Swift

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

0グッド

0クリップ

投稿2017/11/11 18:22

編集2017/11/13 07:39

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

###該当のソースコード

swift

1 func getRoute() 2 { 3 // 現在地と目的地のMKPlacemarkを生成 4 var fromPlacemark = MKPlacemark(coordinate:userLocation, addressDictionary:nil) 5 var toPlacemark = MKPlacemark(coordinate:destLocation, addressDictionary:nil) 6 7 // MKPlacemark から MKMapItem を生成 8 var fromItem = MKMapItem(placemark:fromPlacemark) 9 var toItem = MKMapItem(placemark:toPlacemark) 10 11 // MKMapItem をセットして MKDirectionsRequest を生成 12 let myRequest: MKDirectionsRequest = MKDirectionsRequest() 13 14 15 myRequest.source = fromItem 16 myRequest.destination = toItem 17 myRequest.requestsAlternateRoutes = true 18 myRequest.transportType = MKDirectionsTransportType.any 19 20 let directions = MKDirections(request:myRequest) 21 directions.calculate(completionHandler: { 22 (response:MKDirectionsResponse!, error:NSError!) -> Void in 23 24 _ = response.routes.count 25 if (error != nil || response.routes.isEmpty) { 26 return 27 } 28 var route: MKRoute = response.routes[0] as MKRoute 29 // 経路を描画 30 self.myMap.add(route.polyline) 31 } as! MKDirectionsHandler) 32 //↑ここでエラーメッセージ 33 func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! { 34 let route: MKPolyline = overlay as! MKPolyline 35 let routeRenderer = MKPolylineRenderer(polyline:route) 36 routeRenderer.lineWidth = 5.0 37 routeRenderer.strokeColor = UIColor.red 38 return routeRenderer 39 } 40 }

###試したこと
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 } } }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

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

swift

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

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

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


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

swift

1if error == nil { 2 return 3} 4guard let response = response else { 5 return 6} 7if response.routes.ieEmpty { 8 return 9}

投稿2017/11/13 12:14

編集2017/11/13 17:01
star__hoshi

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問