I am implementing a WeakSet, which wraps its elements weakly in a WeakWrapper so as to not increase their retain count.
My question is, how do I create an iterator so that I can iterate over the elements skipping those that have been deallocated (i.e. are nil).
Please note that I am trying to optimize over the iteration; it's ok if insertion/removal are relatively slower, but there should be little/no performance cost to setting up the iterator.
Here is my WeakSet in its basic form. I can call clean() to remove WeakWrappers whose objects have been deallocated:
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
}
}
I want to be able to do something like this, where the generated elements are the underlying non-nil elements of type T, not the wrapped elements:
class MyObject: NSObject {
func doSomething() { }
}
var weakSet = WeakSet<MyObject>()
for myObject in weakSet {
myObject.doSomething()
}