2017-11-14 1 views
0

mapViewに注釈を追加する際に問題があります。私はこのコードで成功を収めて:addAnnotationsメソッドは、配列の最後の注釈のみを配置します

func placeAnnotations() { 

    for _ in placeDetails { 

     let multipleAnnotations = MKPointAnnotation() 
     multipleAnnotations.title = place.address 
     multipleAnnotations.subtitle = place.phone 
     multipleAnnotations.coordinate = CLLocationCoordinate2D(latitude: place.lat, longitude: place.lng) 
     mapView.addAnnotation(multipleAnnotations) 

    } 

} 

問題があり、それは、このようにカスタムのタイトル、サブタイトルとMKAnnotationViewを示していない、私の場所クラスに準拠していません。これはviewDidLoad()内のコードで、すべての注釈を配置しようとしていますが、最後の注釈だけを追加し続けます。私はそれが配列から以前のものすべてをオーバーライドすることを理解しましたが、実装するための他の方法/方法は見つかりませんでした。

var placeDetails = [Place]() 
    var places = [Place]() 

     override func viewDidLoad() { 
      super.viewDidLoad() 

      downloadPlaceID { 
       for obj in places { 
        place.downloadDetails(input: obj.placeId, completed: { 
         self.placeDetails.append(obj) 
        //self.placeAnnotations() 
    self.mapView.addAnnotations(self.placeDetails) 
        }) 

       } 
      } 
     } 

そして、これは私のすべてのデータがMKAnnotation プロトコルに準拠して、クラス、関数、downloadPlaceID()とdownloadDetails()

class Place: NSObject, MKAnnotation { 

     var coordinate: CLLocationCoordinate2D 
     var placeId: String! 
     var vicinity: String! 
     var phone: String! 
     var workHours: Bool! 
     var lat: Double! 
     var lng: Double! 
     var address: String! 

     var subtitle: String? { 
      return phone 
     } 

     var title: String? { 
      return address 
     } 



     var _placeId: String { 
      if placeId == nil { 
       placeId = "" 
      } 
      return placeId 
     } 

     var _vicinity: String { 
      if vicinity == nil { 
       vicinity = "" 
      } 
      return vicinity 
     } 

     var _phone: String { 
      if phone == nil { 
       phone = "" 
      } 
      return phone 
     } 

     var _workHours: Bool { 
      if workHours == nil { 
       workHours = false 
      } 
      return workHours 
     } 

     var _lat: Double { 
      if lat == nil { 
       lat = 0.0 
      } 
      return lat 
     } 

     var _lng: Double { 
      if lng == nil { 
       lng = 0.0 
      } 
      return lng 
     } 

     var _address: String { 
      if address == nil { 
       address = "" 
      } 
      return address 
     } 



     init(place: [String:Any]) { 

      if let ids = place["place_id"] as? String { 
       self.placeId = ids 
      } 

      if let vicinities = place["vicinity"] as? String { 
       self.vicinity = vicinities 
      } 

      self.coordinate = CLLocationCoordinate2DMake(0.0, 0.0) 

     } 

     func downloadDetails(input: String, completed: @escaping DownloadComplete) { 

      let details = "\(detailsBaseURL)\(detailsPlaceId)\(input)\(detailsKey)\(detailsSearchAPIKey)" 

      Alamofire.request(details).responseJSON { response in 
       let result = response.result 


       if let dictionary = result.value as? [String:Any] { 

        if let result = dictionary["result"] as? [String:Any] { 

         if let phoneNumber = result["formatted_phone_number"] as? String { 
          self.phone = phoneNumber 
         } 

         if let geometry = result["geometry"] as? [String:Any] { 
          if let location = geometry["location"] as? [String:Any] { 
           if let latitude = location["lat"] as? Double { 
            self.lat = latitude 
           } 
           if let longitude = location["lng"] as? Double { 
            self.lng = longitude 
           } 

           self.coordinate = CLLocationCoordinate2DMake(self.lat, self.lng) 

          } 
         } 

         if let openingHours = result["opening_hours"] as? [String:Any] { 
          if let openNow = openingHours["open_now"] as? Bool { 
           self.workHours = openNow 
          } 
         } 

         if let addressComponents = result["address_components"] as? [[String:Any]] { 
          let longName = addressComponents[1]["long_name"] as? String 
          let shortName = addressComponents[0]["long_name"] as? String 

          self.address = "\(longName!),\(shortName!)" 
         } 
        } 
       } 
       completed() 
      } 
     } 
    } 






func downloadPlaceID (completed: @escaping DownloadComplete) { 

     let placeURL = URL(string: nearbyURL) 

     Alamofire.request(placeURL!).responseJSON { (response) in 
      let result = response.result 

      if let dictionary = result.value as? [String:Any] { 
       if let results = dictionary["results"] as? [[String:Any]] { 

        if let status = dictionary["status"] as? String { 
         if status == "OK" { 
          for obj in results { 
           place = Place(place: obj) 
           places.append(place) 
          } 
         } else { 
          print("jede govna") 
         } 
        } 
       } 
      } 
      completed() 
     } 

答えて

0

変数名や概念のいくつかの奇妙な混合がここにありますされていますあなたのコードをいくらか理解しにくくします。

たとえば、vicinitiesという複数の変数をvicinityという単一の属性に割り当てます。または、データモデルからdownloadDetails関数を分離しないでください。

それ以外のところでは、[MKAnnotation]の配列を各ループのマップに追加することで、MKAnnotationsをマップに何度も不必要に追加しているように見えます。

これは、アレイ全体の詳細の更新がいつ完了したかを自分で知ることが難しくなったためです。

すぐに修正するには、downloadDetails関数を、詳細をダウンロードした場所のcompleted関数を呼び出すように変更することをおすすめします。ここでは、あなたがしようとしているものの、実際には単純化されていますが、実際のバージョンです。まず、あなたのPlaceクラス:

var places = [Place]() 
for _ in 1...50 { 
    places.append(Place()) 
} 

for place in places { 
    place.downloadDetails(completed: { (placeWithDetails) in 
     self.mapView.addAnnotation(placeWithDetails) 
    }) 
} 

これを:あなたのビューコントローラで今すぐ

class Place: NSObject, MKAnnotation { 
    var coordinate: CLLocationCoordinate2D 

    override init() { 
     coordinate = CLLocationCoordinate2DMake(0, 0) 
    } 

    func downloadDetails(completed: @escaping (Place) -> Void) { 
     // Instead of downloading details we are just creating random positions 
     self.coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(arc4random_uniform(50)), CLLocationDegrees(arc4random_uniform(50))) 

     // Return the object you've just built 
     completed(self) 
    } 
} 

、ここで私はそれらの詳細を取得し、地図上にそれらを置く、50個のPlaceオブジェクトの配列を始めています50ランダムな場所が移入されたマップでの結果:

iPhone Simulator showing 50 random annotation points on a mapview

+0

こんにちは、それはまだArray..Aの唯一の最後のメンバーを追加しています私は他のポストを通過することを理解していました。一度に1つの注釈を追加していますが、前のものを削除しています。ループを通過するたびにすべての注釈を配置しても、最後にループを通過するときに配列からすべての注釈を残すことが期待されます... func placeAnnotations()を使用すると正しく動作しますが、どのようにそれらの新しく作成されたインスタンスがfunc内でどのようにMKAnnotationに準拠しているのか分かりません。 – NikolaS

+0

私は上記の例を可能な限り単純な例に更新しました。 – Terje

+1

ありがとうございます。あなたのバリエーションを使用し、Placeクラスを2つのクラスに分けました。もう1つはMKAnnotationに準拠しています。 Detailsという名前の他のクラスに属する配列を作成した後、私はすべての注釈を取得して、それらを所望の画像とカスタム記述に適合させました。 – NikolaS

関連する問題