如何从数组中删除协议<>

时间:2017-12-20 00:09:28

标签: arrays swift generics

我认为这很容易,但它不起作用。我有一个数组,我想从中删除一个对象。对象属于类型协议。

var myArray = Array<MyProtocol>()
myArray.remove(at: protocolToRemove) 

从另一个SO问题我看到了一个关于数组扩展的提议,但是当我将扩展名放在另一个文件中时它没有用。

extension Array where Element: Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        if let index = index(of: object) {
            remove(at: index)
        }
     }
}

该协议未实现Equatable

修改 - 添加更多信息

MyProtocol看起来像

protocol MyProtocol {
}

也试过这个,但MyProtocol不是AnyObject,即使只使用类协议。

extension Array where Element: AnyObject {
    mutating func remove(_ element: Element) {
        guard let index = index(where: { $0 === element }) else { return }
        remove(at: index)
    }

    func test() {

    }
} 

2 个答案:

答案 0 :(得分:0)

remove(at:)采用Int(Array的索引)。我假设protocolToRemove不是Int。

  

该协议未实现Equatable

那么remove如何知道要删除哪个元素?如果它不支持==,则唯一的其他选项是===,在这种情况下,协议必须标记为: class。在这种情况下,您可以通过以下方式删除第一个匹配元素:

protocol MyProtocol: class {
    ....
}

if index = myArray.index(where: { $0 === protocolToRemove }) {
    myArray.remove(at: index)
}

答案 1 :(得分:0)

Rob Napier和Leo Dabus让我沿着正确的道路走下去,但是Equatable不是那种可行的方式。

<强>问题

如何从数组&lt;&gt;?

中删除协议

<强>答案

创建仅限课程的协议:

protocol MyProtocol: class {
    //Stuff
}

像这样添加扩展到数组:

extension Array {
    mutating func removeObject(element: Element) {
        guard let index = index(where: { $0 as AnyObject === element as AnyObject}) else { return }
        remove(at: index)
    }
}

用法:

var myArray = Array<MyProtocol>()
var myProtocolImpl = MyProtocolImpl()

myArray.append(myProtocolImpl)
myArray.removeObject(element: myProtocolImpl)

<强>为什么

  • 协议不是AnyObject类型。
  • 使用数组&lt; /协议&GT;从来没有拿起AnyObject扩展。
  • 协议上的Equatable decoration永远不会选择扩展名。
  • 为了删除基于指针地址相等的对象,必须比较内存位置,最好的方法是使用AnyObject进行仅类协议。