I use custom generic Sequence
which stores closures inside:
final class ArrayHolder<T>: Sequence {
var arr = [() -> T?]()
public func add(_ element: @escaping () -> T?) {
arr.append(element)
}
public func makeIterator() -> Array<T>.Iterator {
return arr.compactMap { $0() }.makeIterator()
}
}
I also use generic function over T: AnyObject
to create closure which returns weak object reference:
public func weakify<T: AnyObject>(_ object: T) -> (() -> T?) {
{ [weak object] in object }
}
And I get Segmentation Fault when I call Sequence.forEach
method like this:
let c = MyClass()
let arrHolder = ArrayHolder<MyClass>()
arrHolder.add(weakify(c))
arrHolder.forEach { // Segmentation Fault
print($0)
}
While trying to investigate reasons behind Segmentation Fault, I observed weird behaviour:
// new weakify function with logs
func weakify<T: AnyObject>(_ object: T) -> (() -> T?) {
weak var obj: T? = object
return {
if obj == nil {
print("weakify nil")
} else {
print("weakify non nil") // prints "weakify non nil"
}
return obj
}
}
// modified call side
arrHolder.add(weakify(c))
let notNils = arrHolder.arr.compactMap {
let res = $0()
if let res {
print("compact map not nil")
} else {
print("compact map nil") // prints "compact map nil"
}
return res
}
print(notNils.count, arrHolder.count) // prints 0, 1
Surely, some dark magic is hidden there.
I don't know what to do next.
Thanks in advance.