gpt4 book ai didi

swift - 实现跳过 WeakSet 中的 nil 元素的自定义迭代器

转载 作者:搜寻专家 更新时间:2023-10-31 08:30:05 26 4
gpt4 key购买 nike

我正在实现一个 WeakSet,它将其元素弱包装在 WeakWrapper 中,以免增加它们的保留计数。

我的问题是,如何创建一个迭代器,以便我可以迭代跳过那些已被释放的元素(即 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
}
}

我希望能够做这样的事情,其中​​生成的元素是 T 类型的底层非 nil 元素,而不是包装元素:

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())
}
}

从集合的惰性 View 开始,它的(惰性)集合非 nil 对象是使用 flatMap 创建的。

它也可以在没有 lazy 的情况下工作,但随后是一个所有非 nil 的数组makeIterator() 被调用后,对象立即被创建。

另一种解决方案,使用自定义迭代器类型:

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())
}
}

关于swift - 实现跳过 WeakSet 中的 nil 元素的自定义迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46386758/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com