参数类型不符合预期类型 MKAnnotation

Argument type does not conform to expected type MKAnnotation

我将这篇文章用作参考 https://www.thorntech.com/2016/01/how-to-search-for-location-using-apples-mapkit/ 构建我的应用程序 我尝试在 searchBarText 相等时使用 matchingItem,然后附加到 matchingItems。 我目前有一条错误消息 参数类型 'ServiceLocation' 不符合预期类型 'MKAnnotation' 这意味着我需要更改 matchingItem 的变量类型。 当您希望稍后存储 ServiceLocation 以用作 MapView 时,我不确定什么是最好的变量类型。 有什么建议吗?

var matchingItems = [MKAnnotation]()
        var handleMapSearchDelegate:HandleMapSearch? = nil
    var allServiceLocations : [ServiceLocation] = []
        
        func updateSearchResults(for searchController: UISearchController) {
            
           
            matchingItems = []
            guard let mapView = mapView,
                let searchBarText = searchController.searchBar.text else { return }
            for location in allServiceLocations{
                if(location.locationName == searchBarText){
                   matchingItems.append(location)
                    
                }
            }

ServiceLocation.swift

struct ServiceLocation: Codable {
    var id: Int
    var locationType : LocationType
    var locationName: String
    var latitude: Double
    var longitude: Double
    var active: Bool
    var home : Bool
    var numAvailableChargers : Int
    var acronym : String?
    var eta: Int?
}

所以编译器告诉你的是,你有一个 MKAnnotation 的数组,但你试图将一个 ServiceLocation 填充到其中,这是一个不相关的类型。由于 Swift 是强类型的,这只是无效的(方钉 - 圆孔情况)。

您需要做的是将 ServiceLocation 映射到 MKAnnotation,例如像这样:

var matchingItems = [MKAnnotation]()
var handleMapSearchDelegate:HandleMapSearch? = nil
var allServiceLocations : [ServiceLocation] = []
        
func updateSearchResults(for searchController: UISearchController) {
      guard let mapView = mapView,
            let searchBarText = searchController.searchBar.text else { return }

        matchingItems = allServiceLocations.filter({ [=10=].locationName == searchBarText })
        .map({ 
            let annotation = MKPointAnnotation()
            annotation.coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(exactly: [=10=].latitude)!, longitude: CLLocationDegrees(exactly: [=10=].longitude)!)
            annotation.title = [=10=].locationName
            annotation.subtitle = [=10=].locationType
        return annotation
       })
}

几个选项:

  1. 您可以将 ServiceLocation 设为注释,方法是将其设为符合 MKAnnotationNSObject 子 class。因此,首先将其设为 class:

     class ServiceLocation: NSObject, Codable {
         var id: Int
         var locationType: LocationType
         var locationName: String
         var latitude: Double
         var longitude: Double
         var active: Bool
         var home: Bool
         var numAvailableChargers: Int
         var acronym: String?
         var eta: Int?
    
         init(id: Int, locationType: LocationType, locationName: String, latitude: Double, longitude: Double, active: Bool, home: Bool, numAvailableChargers: Int, acronym: String?, eta: Int?) {
             self.id = id
             self.locationType = locationType
             self.locationName = locationName
             self.latitude = latitude
             self.longitude = longitude
             self.active = active
             self.home = home
             self.numAvailableChargers = numAvailableChargers
             self.acronym = acronym
             self.eta = eta
    
             super.init()
         }
     }
    

    其次,添加 MKAnnotation 协议与一些计算属性的一致性:

     extension ServiceLocation: MKAnnotation {
         var coordinate: CLLocationCoordinate2D { CLLocationCoordinate2D(latitude: latitude, longitude: longitude) }
         var title: String? { locationName }
         var subtitle: String? { "\(numAvailableChargers) chargers" }
     }
    
  2. 或者,您可以创建一个注释 class,将您的原始服务位置 struct 作为 属性:

     class ServiceLocationAnnotation: NSObject, MKAnnotation {
         var coordinate: CLLocationCoordinate2D { CLLocationCoordinate2D(latitude: serviceLocation.latitude, longitude: serviceLocation.longitude) }
         var title: String? { serviceLocation.locationName }
         var subtitle: String? { "\(serviceLocation.numAvailableChargers) chargers" }
    
         let serviceLocation: ServiceLocation
    
         init(serviceLocation: ServiceLocation) {
             self.serviceLocation = serviceLocation
             super.init()
         }
     }
    

    这个想法还有其他排列,但关键是只做一个注释,把你的 struct 作为 属性,然后,而不是添加 ServiceLocation在地图的注释中,添加 ServiceLocationAnnotation.

显然,您可以随心所欲地制作字幕,但希望这能说明这个想法。