Swift 4.1中泛型数组的弱引用到类绑定协议

11

我正在尝试创建一个通用的 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协议,还有许多毫无共同之处的协议,这就是为什么我想要首先将其变成通用的原因。

1个回答

3

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

但这只是把问题推到了另一个地方,因为我最终想要的是协议实现者的数组,而不是具体类型。 - FSMaxB
你可能需要一个类型擦除器,就像我链接的问答中讨论的那样。 - Martin R
@FSMaxB:你只需要一个类型擦除器来处理Observable协议,而不是每个符合条件的类型都需要一个。请查看更新。 - Martin R
但这仍然不适用于不同的观察者协议。 - FSMaxB
@FSMaxB:我强烈认为你需要每个协议一个类型擦除器,正如我链接的问答中所指出的。 - Martin R
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接