通过自定义协议符合协议 MKAnnotation

Conform to Protocol MKAnnotation via Custom Protocol

我想轻松地在地图上获得 2 个或更多不同的对象类型。 Swift 2.0,我想使用协议。

我创建了一个协议,这些对象也需要遵守。我假设现在任何符合 PinProtocol 的项目在本质上与 MKAnnotation 相同......只是更多!

protocol PinProtocol: MKAnnotation {
    // stuff
}

我有 2 个 类,员工和客户

都符合PinProtocol(然后还需要符合MKAnnotation)

我知道这就像我设置 class 一样有效,

class Client: NSObject, PinProtocol {
     //var coordinate:CLLocationCoordinate2D // Leave out get doesn't conform to protocol warning as expected
}

所以,这告诉我 PinProtocol 正在按预期工作,因为需要遵守 PinProtocol 的项目也符合 MKAnnotation 协议。因为coordinate:CLLocationCoordinate2D,是MKAnnotation需要的。

那么为什么我会遇到这个问题

let staffAndClients = [PinProtocol]()

mapView.addAnnotations(staffAndClients) // not allowed!
//mapView.addAnnotations(pins as! [MKAnnotation]) // also not allowed

错误是,无法将类型 [PinProtocol] 的值转换为预期参数 [MKAnnotation]

PinProtocol 不符合 MKAnnotation,所以应该可以工作。

但这样做效果很好

let staff = [Staff]()
mapView.addAnnotations(staff) // no problem
let clients = [Client]()
mapView.addAnnotations(clients) // no problem

我可以使用 AnyObject 解决这个问题,但为什么我不能使用 PinProtocol - 对我来说这似乎更清晰并且是协议扩展的全部想法。

感谢您的帮助。

添加...

对于那些面临类似问题的人,我的解决方法是

var pins = [AnyObject]()
mapView.addAnnotations(pins as! [MKAnnotation])

protocol 视为模板,您可以使用该模板制作一些有用的东西,例如学校演示文稿,但您不能将模板本身用于任何演示文稿。

那是因为协议缺少方法或属性的实现。要真正获得该特定协议的对象,需要实现这些方法。在这种情况下,Java 允许您匿名子 class 一个协议,并强制您实现所需的方法。 (Java叫interface,不要混淆Objective-C interface

不像java,Swift不支持创建匿名子classes,所以任何本身就是协议的class都不能在[=中创建对象58=] 和 Swift。实例化它们的唯一方法是让另一个 class(Objective C 中的 interface)符合该协议并创建特定 class、StaffClient 在你的情况下。但是,您可以使用协议类型的变量,如下所示:

let staff = [PinProtocol]() //PinProtocol type array. can hold any type of objects that conform to this protocol

staff 在这种情况下是类型 PinProtocolArray,它不知道有关创建的对象的任何其他信息。

编辑:

我刚刚正确理解了你的问题。是的,我们可以通过 protocol 名称声明一个类型为 swift 的数组。并且该数组可以保存符合协议的 classes 对象。您声明数组的语法是正确的。

let staffAndClients = [PinProtocol]()

关于错误 错误是,无法将类型 [PinProtocol] 的值转换为预期的参数 [MKAnnotation] 我查看了文档,发现addAnnotations() 方法接受 AnyObject 的数组如下:

func addAnnotations(annotations: [AnyObject]!) //in MKMapView 

现在棘手的部分是,MKAnnotation 不是从 AnyObject 继承的,而是从 NSObjectProtocol 继承的,即:

protocol MKAnnotation : NSObjectProtocol

AnyObject 也继承自 NSObjectProtocol,使其成为 MKAnnotation 的同级,这就是为什么会出现错误,因为您不能传递类型为 MKAnnotation 的对象,因为它们不在父层次结构中 AnyObject

在处理完 MapViewController 数据源的麻烦后

var pins = [AnyObject]()

我意识到我可以轻松避免类型检查的所有相关问题并使用首选的 PinProtocols 数组

var pins = [PinProtocol]()

解决方法很简单

func addToMap() {
    let mappingPins = pins.map{ [=12=] as AnyObject }
    mapView.addAnnotations(mappingPins as! [MKAnnotation])
    mapView.showAnnotations(mappingPins as! [MKAnnotation], animated: true)
}