【问题标题】:Generic Array of weak references to class bound protocol in Swift 4.1Swift 4.1 中对类绑定协议的弱引用的通用数组
【发布时间】:2019-01-19 07:45:23
【问题描述】:

我正在尝试创建一个可以放入数组的通用 WeakReference 类型(并最终创建一个通用的弱数组类型)。

到目前为止一切顺利,但代码如下:

class WeakReference<ElementType: AnyObject> {
    weak var element: ElementType?

    init(_ element: ElementType) {
        self.element = element
    }
}

protocol Element: AnyObject {}

class WeakElementHolder {
    var weakElements: [WeakReference<Element>] = []
}

产生此编译器错误:

WeakReference.swift:12:21: error: 'WeakReference' requires that 'Element' be a class type
    var weakElements: [WeakReference<Element>] = []
                       ^
WeakReference.swift:1:7: note: requirement specified as 'ElementType' : 'AnyObject' [with ElementType = Element]
class WeakReference<ElementType: AnyObject> {
  ^

这很奇怪,因为协议肯定需要一个类 (AnyObject)。

奇怪的是,如果我省略了泛型,一切都会正常工作:

protocol Element: AnyObject {}

class WeakElementReference {
    weak var element: Element?

    init(_ element: Element) {
        self.element = element
    }
}

class WeakElementHolder {
    var weakElements: [WeakElementReference] = []
}

四处搜索我找到了this question,但没有得到真正的回答。

是否有一种解决方法仍然可以以某种方式实现与类绑定协议一起使用的通用弱引用数组?

更新:

我的具体用例是存储一个观察者列表,当事情发生时会得到通知:

protocol Observer: AnyObject {
    func notify()
}

class WeakReference<ElementType: AnyObject> {
    weak var element: ElementType?

    init(_ element: ElementType) {
        self.element = element
    }
}

class WeakArray<ElementType: AnyObject> {
    var content: [WeakReference<ElementType>] = []
}

class Observable {
    var observers: WeakArray<Observer>()

    func notifyAllObservers() {
        // call notify() on all observers here
    }
}

这些观察者可以是许多不同的具体类型。

更多说明: 不仅有一个Observer 协议,还有很多没有共同点,这就是为什么我首先希望它是通用的。

【问题讨论】:

    标签: arrays swift generics weak-references swift-protocols


    【解决方案1】:

    Protocol doesn't conform to itself? 中所述,(非@objc)协议由

    protocol Element: AnyObject {}
    

    继承自AnyObject,但不符合AnyObject

    使用类型橡皮擦的可能解决方案:

    protocol Observer: AnyObject {
        func notify()
    }
    
    struct AnyObserver {
        weak var base: Observer?
    
        init(_ base: Observer ) {
            self.base = base
        }
    }
    
    class Observable {
        var observers: [AnyObserver] = []
    
        func add(_ observer: Observer) {
            observers.append(AnyObserver(observer))
        }
    
        func notifyAllObservers() {
            for observer in observers {
                observer.base?.notify()
            }
        }
    }
    

    示例用法:

    class A: Observer {
        func notify() {
             print("Hello A")
        }
    }
    
    class B: Observer {
        func notify() {
            print("Hello B")
        }
    }
    
    let a = A()
    let b = B()
    
    let o = Observable()
    o.add(a)
    o.add(b)
    
    o.notifyAllObservers()
    // Hello A
    // Hello B
    

    【讨论】:

    • 但这只会解决问题,因为我最终想要一个协议元素数组,而不是具体类型。
    • 您可能需要一个类型橡皮擦,正如我链接到的问答中所讨论的那样。
    • 但是泛型的全部意义又消失了,因为我需要为每种观察者使用类型橡皮擦,并为每种观察者使用泛型弱数组。
    • 也许只是swift无法表达的东西。
    • @FSMaxB:对于 Observable 协议,您只需要一个类型的橡皮擦,而不是每个符合类型的橡皮擦。查看更新。
    猜你喜欢
    • 2016-08-17
    • 2018-05-21
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多