我正在实现一个WeakSet
,将其元素弱地包装为a WeakWrapper
,以便不增加其保留数。
我的问题是,如何创建一个迭代器,以便可以跳过已被释放的元素(即are nil
)来遍历这些元素。
请注意,我正在尝试优化迭代;插入/删除相对较慢是可以的,但是设置迭代器的性能成本应该很小/没有。
这是我WeakSet
的基本形式。我可以致电clean()
移除WeakWrapper
其对象已被释放的:
struct WeakSet<T> where T: AnyObject & Hashable {
private var set: Set<WeakWrapper<T>> = []
mutating func insert(_ elem: T) {
self.set.insert(WeakWrapper<T>(elem))
}
mutating func remove(_ elem: T) {
self.set.remove(WeakWrapper<T>(elem))
}
mutating func clean() {
for elem in set {
if elem.obj == nil {
self.set.remove(elem)
}
}
}
}
fileprivate class WeakWrapper<T>: Hashable where T: AnyObject {
weak var obj: T?
let hashValue: Int
init(_ obj: T) {
self.obj = obj
self.hashValue = ObjectIdentifier(obj).hashValue
}
static func ==(lhs: WeakWrapper, rhs: WeakWrapper) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
我希望能够做这样的事情,其中生成的元素是type的基础非null元素T
,而不是包装的元素:
class MyObject: NSObject {
func doSomething() { }
}
var weakSet = WeakSet<MyObject>()
for myObject in weakSet {
myObject.doSomething()
}
一种可能的解决方案,使用Swift标准库中的内置方法:
extension WeakSet: Sequence {
func makeIterator() -> AnyIterator<T> {
return AnyIterator(self.set.lazy.flatMap { $0.obj }.makeIterator())
}
}
从该集合的惰性视图开始,使用创建其非nil对象的(惰性)集合flatMap
。
它也可以在不使用的情况下工作lazy
,但是一旦makeIterator()
被调用,就会急切地创建一个包含所有非nil对象的数组。
使用自定义迭代器类型的另一种解决方案:
struct WeakSetIterator<T>: IteratorProtocol where T: AnyObject {
fileprivate var iter: SetIterator<WeakWrapper<T>>
mutating func next() -> T? {
while let wrapper = iter.next() {
if let obj = wrapper.obj { return obj }
}
return nil
}
}
extension WeakSet: Sequence {
func makeIterator() -> WeakSetIterator<T> {
return WeakSetIterator(iter: self.set.makeIterator())
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句