首页 > 解决方案 > Swift 4.1 中对类绑定协议的弱引用的通用数组

问题描述

我正在尝试创建一个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] = []
}

环顾四周,我发现了这个问题,但并没有真正得到答案。

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

更新:

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

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协议,还有许多没有共同点,这就是为什么我首先希望它是通用的。

标签: arraysswiftgenericsweak-referencesswift-protocols

解决方案


正如协议中所讨论的不符合自身?,(非@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

推荐阅读