Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有协议对象的纯swift集_Swift_Set_Protocols - Fatal编程技术网

带有协议对象的纯swift集

带有协议对象的纯swift集,swift,set,protocols,Swift,Set,Protocols,有没有一种方法可以使以下各项真正起作用 V1-“测试协议不符合哈希表” 协议测试协议{ // } 课堂测试{ var s:设置? init(){ } } V2-“协议“testProtocol”只能用作一般约束,因为它具有自身或关联的类型要求 协议testProtocol:Hashable{ // } 课堂测试{ var s:设置? init(){ } } 我假设答案是否定的——因为协议(即使带有@objc标记)没有足够的信息??但可能我在这里遗漏了一些行或东西。也许有更好的解决方案,但您可

有没有一种方法可以使以下各项真正起作用

V1-“测试协议不符合哈希表”
协议测试协议{
//
}
课堂测试{
var s:设置?
init(){
}
}
V2-“协议“testProtocol”只能用作一般约束,因为它具有自身或关联的类型要求
协议testProtocol:Hashable{
//
}
课堂测试{
var s:设置?
init(){
}
}

我假设答案是否定的——因为协议(即使带有@objc标记)没有足够的信息??但可能我在这里遗漏了一些行或东西。

也许有更好的解决方案,但您可以将类设置为泛型:

protocol testProtocol : Hashable {
    //
}

class test<P: testProtocol> {
    var s : Set<P>?

    init() { }
}
协议testProtocol:Hashable{
//
}
课堂测试{
变量s:设置

? init(){} }


一种解决方案是将集合包装在一个类或结构中,并约束插入函数,使其仅接受符合您的协议且可哈希的项。然后,您可以在实现中使用
AnyHashable
集合

例如:

protocol MyProtocol {
    func doStuff()
}

class MyProtocolSet {
    var set = Set<AnyHashable>()

    func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
        set.insert(AnyHashable(item))
    }

    func iterate( doing: (MyProtocol) -> Void ) {
        for item in set {
            doing(item as! MyProtocol)
        }
    }
}

struct Foo: MyProtocol, Hashable {
    func doStuff() { print("foo") }
}

struct Bar: MyProtocol, Hashable {
    func doStuff() { print("bar") }
}

func test() {
    let set = MyProtocolSet()
    set.insert(Foo())
    set.insert(Bar())
    set.iterate { (item: MyProtocol) in
        item.doStuff()
    }
}
协议MyProtocol{
func doStuff()
}
类MyProtocolSet{
var set=set()
func insert(uitem:T),其中T:MyProtocol,T:Hashable{
set.insert(任意散列(项目))
}
func迭代(执行:(MyProtocol)->Void){
对于集合中的项目{
正在执行(项目为!MyProtocol)
}
}
}
struct Foo:MyProtocol,可哈希{
func doStuff(){print(“foo”)}
}
结构栏:MyProtocol,可哈希{
func doStuff(){print(“bar”)}
}
func测试(){
let set=MyProtocolSet()
set.insert(Foo())
set.insert(Bar())
set.iterate{(项:MyProtocol)在
项目.doStuff()
}
}
通过对插入函数施加约束,您可以说“这个集合必须包含符合协议的内容,并且是可散列的”,而不是实际将协议约束为可散列的


如果包装集类本身可以是泛型的,并接受协议来遵循,那就更好了,但我还没有弄清楚这是否可行!

我知道这不是一个
集(就像所问的问题),但您可以使用
NSHashTable
而不是
。不过,您必须向objc公开您的协议。虽然不是
,但如果您只是希望存储协议对象的集合,而不必遵守
哈希表
,这将起作用:

@objc protocol testProtocol { }
class Object {
    var s: NSHashTable<testProtocol>!
}
@objc协议testProtocol{}
类对象{
var s:那是一张桌子!
}
这样,您就可以使用提供的
添加
删除
功能

此外,如果您正在存储观察者或任何类似内容,则可以使用
NSHashTable.weakObjects()
初始化哈希表,这将确保不会保留对象


以下是有关
NSHashTable

的更多信息,但这意味着您的集合的对象都需要共享一个类(或超类),这意味着您添加了另一个要求。这是否意味着您不能在Swift中创建仅受协议一致性约束的
集合
?@Zack:问题是Hashable继承自具有“自我要求”的可平等协议,在这种情况下,运算符
func==(lhs:Self,rhs:Self)->Bool
。是的,我知道这一点。虽然我个人认为,在2.0的语言设计中,让
均衡化要求您比较的两个项目具有相同的类层次结构是一个错误。我在苹果的Swift开发论坛上问过这个问题,希望他们会有一个建议,而不是分叉
均衡uatable
Hashable
Set
允许比较不同类层次结构的项。@扎克:我无法判断这是否是一个好的设计决策。或许可以看看“面向协议的Swift编程”“WWDC会议视频,其中解释了这背后的基本原理。我实际上是在会议室里:DThanks!!!它真的帮助了我。我只是不强迫演员们去做(项目为!MyProtocol)。干杯
protocol MyProtocol {
    func doStuff()
}

class MyProtocolSet {
    var set = Set<AnyHashable>()

    func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
        set.insert(AnyHashable(item))
    }

    func iterate( doing: (MyProtocol) -> Void ) {
        for item in set {
            doing(item as! MyProtocol)
        }
    }
}

struct Foo: MyProtocol, Hashable {
    func doStuff() { print("foo") }
}

struct Bar: MyProtocol, Hashable {
    func doStuff() { print("bar") }
}

func test() {
    let set = MyProtocolSet()
    set.insert(Foo())
    set.insert(Bar())
    set.iterate { (item: MyProtocol) in
        item.doStuff()
    }
}
@objc protocol testProtocol { }
class Object {
    var s: NSHashTable<testProtocol>!
}