Swift中的设置和协议

Gaé*_*anZ 17 ios swift

我想初始化一个Set,其中包含与Hashable协议和自定义协议相对应的值.

我试过了 :

protocol CustomProtocol: Hashable {}

let set = Set<CustomProtocol>()
Run Code Online (Sandbox Code Playgroud)

但是Xcode抱怨道:

不支持使用'CustomProtocol'作为符合协议'Hashable'的具体类型

我怎样才能做到这一点?

提前致谢.

mat*_*att 9

你不能做你想做的事情的直接原因是Hashable是一种通用协议.因此,它 - 或从中派生的协议 - 不能用作Set的元素类型.泛型类型只能用作另一个泛型中的约束.您会注意到Set<Hashable>,即使set的元素类型必须符合 Hashable ,也不能声明其中任何一个.

最简单的方法是制作一组协议,而不是一组对象类型.例如,如果S是符合CustomProtocol的结构(因为它符合Hashable加上CustomProtocol所需的任何其他内容),则可以声明一组S.

例:

protocol CustomProtocol: Hashable {

}

func ==(lhs:S,rhs:S) -> Bool {
    return lhs.name == rhs.name
}

struct S : CustomProtocol {
    var name : String
    var hashValue : Int { return name.hashValue }
}

let set = Set<S>()
Run Code Online (Sandbox Code Playgroud)

如果你想要解决的问题是你想要一个混合类型的集合,但它们在某种程度上是彼此相同的,那么协议扩展就解决了同样的问题,正如协议中的讨论所解释的那样 - 面向WWDC 2015的视频.

但是,只需要创建从NSObject派生的所有类型类就更简单了.当然,你仍然可以让它们采用一些辅助协议,但是这个集合不会被定义为一组协议而是NSObject.


Gaé*_*anZ 5

在 Swift 3 中,一种解决方案是使用AnyHashable 结构

例如,要创建一个 Observers/Observable 模式,我们可以这样做:

protocol Observer {
    func observableDidSomething(_ observable: Observable)
}

class Observable {
    private var observersSet: Set<AnyHashable> = []

    private var observers: [Observer] {
        return observersSet.flatMap { $0 as? Observer }
    }

    func add<O>(_ observer: O) where O : Observer, O : Hashable {
        observersSet.insert(observer)
    }

    func remove<O>(_ observer: O) where O : Observer, O : Hashable {
        observersSet.remove(observer)
    }

    // ...

    private func doSomething() {
        // do something ...
        observers.forEach { $0.observableDidSomething(self) }
    }
} 
Run Code Online (Sandbox Code Playgroud)

请注意,我将Hashable协议与我的协议分开Observer