Ios Swift中的Set和protocols

Ios Swift中的Set和protocols,ios,swift,Ios,Swift,我想用与哈希协议和自定义协议相对应的值初始化一个集合 我试过: protocol CustomProtocol: Hashable {} let set = Set<CustomProtocol>() protocol-CustomProtocol:Hashable{} 设set=set() 但Xcode抱怨: 使用“CustomProtocol”作为符合协议的具体类型 不支持“Hashable” 我怎样才能做到这一点 提前感谢。您不能做您想做的事情的直接原因是Hashable

我想用与哈希协议和自定义协议相对应的值初始化一个集合

我试过:

protocol CustomProtocol: Hashable {}

let set = Set<CustomProtocol>()
protocol-CustomProtocol:Hashable{}
设set=set()
但Xcode抱怨:

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

我怎样才能做到这一点


提前感谢。

您不能做您想做的事情的直接原因是Hashable是一个通用协议。因此,它或从它派生的协议不能用作集合的元素类型。泛型类型只能用作另一个泛型中的约束。您将注意到,即使集合的元素类型必须符合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>()
协议自定义协议:可哈希{
}
func==(左:S,右:S)->Bool{
返回lhs.name==rhs.name
}
结构S:CustomProtocol{
变量名称:String
var hashValue:Int{return name.hashValue}
}
设set=set()
如果您试图解决的问题是您想要一个混合类型的集合,这些类型在某种程度上彼此相等,那么这就是协议扩展解决的同一个问题,正如面向协议的WWDC 2015视频中的讨论所解释的


但是,只制作所有从NSObject派生的类型类会更简单。当然,您仍然可以让他们采用一些辅助协议,但集合不会被定义为该协议的集合,而是NSObject的集合。

在Swift 3中,一个解决方案是使用

例如,要创建观察者/可观察模式,我们可以:

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) }
    }
} 
协议观察者{
func ObservabledSomething(uObservable:observable)
}
类可观测{
私有变量observersSet:Set=[]
私人var观察员:[观察员]{
返回observersSet.flatMap{$0 as?Observer}
}
func add(observer:O),其中O:observer,O:Hashable{
ObserverSet.insert(观察者)
}
func remove(observer:O)其中O:observer,O:Hashable{
ObserverSet.remove(观察者)
}
// ...
私人func doSomething(){
//做点什么。。。
observators.forEach{$0.observatedsomething(self)}
}
} 

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

对象分开,它们已经被要求符合Hashable。如果CustomProtocol不符合Hashable,Xcode会抱怨CustomProtocol不符合它。我好像错过了什么。谢谢。但是我想在我的集合中插入来自不同类的对象,而不是单个类。这就是为什么我不想创建一个“协议集”。请参阅我修改后的答案。当然,最简单的方法就是让所有类都从NSObject派生,正如您已经得到的建议。我正在寻找一个听起来像协议扩展的答案。视频出来时我看了,但我不知道在那种情况下如何使用这种方法。目前,一个数组可以完成这项工作。我以后再看。(顺便说一句,我喜欢你的书,我很高兴你回答了我的一个问题)在视频中,问题是定义协议的可等分性,这是你在使用CustomProtocol时面临的问题-我们如何知道两个CustomProtocol采用者之间是
==
?如果没有回答这个问题的
==
的定义,我们就无法实现Hashable。他通过协议扩展constrained
解决了这个问题,其中Self:equalable
定义了一个额外的等价函数。通过这种方式,您将能够保证
==
对于任何一对集合成员都是有意义的。我不会重复他的代码,因为你想做的正是他所做的。