質問: annotation } else { print("画像を取得できませんでした:画像はありません") } } else { print("何らかの理由で応答コードを取得できませんでした") } } } downloadPicTask.resume() } } return pinView } self.mapView.addAnnotations(annotationArray) } } } } } ``` ### 補足情報(言語/FW/ツール等のバージョンなど) * swift3 * xcode8.3.3
回答: コメントに示したようにどこからどこまでをどんな方法で動作確認されたのかが全くわかりませんので、具体的に動作確認ができる形でのコードをお示しすることができないのですが、ざっと見ただけでも大幅に修正しなければ動くようにはできないので、概要だけでもお伝えしておきます。 あなたのコードの大枠を示すと以下のようになっています。 ``` // ↓(1) func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! { if annotation === mapView.userLocation { // 現在地を示すアノテーションの場合はデフォルトのまま return nil } else { //配列の該当のデータをitemという定数に代入? let items = contentArray //... for item in items { //itemの中身を辞書型に変換? let content = item.value as! Dictionary for (key, element) in content{ let pinData = content[key] as! [String: Any] if let geohash = pinData["geohash"] as? String { let (latitude, longitude) = Geohash.decode(hash: geohash)! let annotation = MKPointAnnotation() //-> (4) annotation.coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(latitude.min), CLLocationDegrees(longitude.min)) annotationArray.append(annotation) //-> (5) let reuseId = "pin" if let pinView = self.mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) { return pinView //-> (2) } else { // 再利用できるアノテーションが無い場合(初回など)は生成する let pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId) //... return pinView //-> (2) } self.mapView.addAnnotations(annotationArray) //-> (3) } } } } } ``` (1) お示しのメソッドヘッダーはSwift 2までのものです。Swift 3では、同じ`MKMapViewDelegate`のメソッドは次のようになります。 ``` func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { //... } ``` Swiftはまだ発展途上の言語で、とりわけSwift 2→3では、ほぼ全ての実用的なアプリで大幅に修正が必要な変更が加えられました。ネット上から参考コードを引っ張ってくるような場合には、記事内容がご自身の使っているSwiftと同バージョンかどうかを確認しないと、SwiftやiOSのプログラミングよりも、Swiftの言語変遷史を学習する羽目になってしまいます。お気をつけください。 (2) あなたがこのメソッドに対する`return`文を書いているのは、(`annotation === mapView.userLocation`が成立する場合の`nil`を除けば)`if let geohash = pinData["geohash"] as? String`の条件が成立する場合だけになっています。その条件を満たすデータがひとつも`contentArray`の中に存在しない場合に実行されるような`return`文がありません。そのために`Missing return`のエラーが発生しています。 (3) 通常`mapView(_:viewFor:)`メソッドの中で、`MKMapView.addAnnotations(_:)`を呼ぶことはあり得ません。`addAnnotations(_:)`はどこか別の場所で、地図が表示される前に実行しておいて、`mapView(_:viewFor:)`メソッドでは単に`annotation`パラメーターで示されるアノテーション用の`MKAnnotationView`を返します。 (4) 上記しましたが、あなたのコードにあるように`annotation`パラメーターを無視してしまって別の`MKAnnotation`インスタンス(`MKPointAnnotation`)を`mapView(_:viewFor:)`メソッド内で作成するなんてことは通常あり得ません。 (5) `annotationArray`の宣言がメソッド内には見当たりませんから、これはインスタンスプロパティなのでしょうか。この配列に対する`append(_:)`は行なっていますが、配列の中身を空にするコードは見当たりません。と言うことは、`mapView(_:viewFor:)`メソッドが呼ばれるたび(`MKMapView`の表示中はかなり頻繁に呼び出されます)に配列の内容が膨れ上がっていくことになります。 ざっくりと修正の方針を示すと以下のようになります。 * 「`contentArray`からアノテーションを作成して`addAnnotations(_:)`を行う処理」は、`mapView(_:viewFor:)`の他のメソッド(`viewDidLoad()`かアノテーションが確定するようなアクションメソッド、当然ながら同じアノテーションを何度も`addAnnotations(_:)`してはいけない)の中に移動させる。(この時点で作成するのは`MKAnnotation`の実装クラスであり、`MKAnnotationView`ではない。) * `mapView(_:viewFor:)`では、`annotation`パラメーターを元に作成した`MKMapAnnotationView`を一つ返す。そのために必要なプロパティが既存の`MKAnnotation`クラスに存在しないのであれば、オリジナルの`MKAnnotation`クラスを作成する。 大幅修正が必要となるでしょうから、上記の方針を元にコンパイルが通る程度のコードにまで修正できたら、まだ所望の動作と異なる部分が出たとしても個別に別質問としていただいた方が良いでしょう。