在快速的代理数组中查找委托

时间:2014-12-17 19:01:44

标签: ios swift delegates

我想在删除之前检查我的removeDelegate方法中是否已有委托。 我怎么做?

这是我到目前为止所得到的:

protocol LocationManagerDelegate {
    func locationManagerDidUpdateLocation(
        oldLocation: CLLocationCoordinate2D,
        currentLocation: CLLocationCoordinate2D
    )
}

class LocationManager: NSObject {
    private var _delegates = [LocationManagerDelegate]()

    func removeDelegate(delegate:LocationManagerDelegate) {
        if contains(_delegates, delegate) {
            // Remove delegate
        }
    }
}

但是,这会在' if contains'上给出以下错误。 line:

无法调用'包含'使用类型'的参数列表(@ lvalue Array< LocationManagerDelegate>!,LocationManagerDelegate)'

2 个答案:

答案 0 :(得分:11)

Swift 3的更新:

假设委托实际上是的实例,您可以在协议中要求"继承"来自" class":

protocol LocationManagerDelegate: class {
    // ...
}

然后使用" indentitiy运算符使用index(where:)方法 ===

class LocationManager: NSObject {
    private var _delegates = [LocationManagerDelegate]()

    func removeDelegate(delegate:LocationManagerDelegate) {
        if let index = _delegates.index(where: { $0 === delegate }) {
            _delegates.remove(at: index)
        }
    }
}

旧答案(Swift 1):

有两种略有不同的contains()功能:

func contains<S : SequenceType where S.Generator.Element : Equatable>(seq: S, x: S.Generator.Element) -> Bool

func contains<S : SequenceType, L : BooleanType>(seq: S, predicate: (S.Generator.Element) -> L) -> Bool

您正在使用第一个,这要求序列元素符合 Equatable协议,即可以与==进行比较。

假设委托实际上是的实例,您可以要求 在协议中通过&#34;继承&#34;来自&#34; class&#34;:

protocol LocationManagerDelegate : class {
    // ...
}

然后使用第二个基于谓词的contains()版本 身份运营商===

func removeDelegate(delegate:LocationManagerDelegate) {
    if contains(_delegates, { $0 === delegate }) {
        // Remove delegate
    }
}

要从数组中删除对象,您必须获取其索引,因此您可以使用 来自https://stackoverflow.com/a/25543084/1187415findIdenticalObject()函数:

func findIdenticalObject<T : AnyObject>(array: [T], value: T) -> Int? {
    for (index, elem) in enumerate(array) {
        if elem === value {
            return index
        }
    }
    return nil
}

然后使用

查找并从数组中删除
func removeDelegate(delegate:LocationManagerDelegate) {
    if let index = findIdenticalObject(_delegates, delegate) {
        _delegates.removeAtIndex(index)
    }
}

答案 1 :(得分:1)

contains的参数必须实现Equatable协议,因为它被定义为:

public func contains<T:Equatable>(left:[T], right:T) -> Bool

由于没有办法表明LocationManagerDelegate实现了Equatable,我认为你不能使用它。显而易见的尝试是:

protocol LocationManagerDelegate : Equatable {
    ...
}

但是当你尝试声明数组时会失败,因为Equatable使用Self。

我能想出的最佳选择是:

func removeDelegate(delegate:LocationManagerDelegate) {
    _delegates = filter(_delegates) { return $0 !== delegate }
}