I have a class A
that stores a optional weak variable
to other object, that is a subclass
of A
. Sometimes when I store something in this variable I get a leak
- this happens rarely, but it does. I'm assigning this variable in forEach loop
, but I also found similar leak in other place of application once when using weak var
, so I don't think that loop has anything to do with this. Responsible library is libswiftCore.dylib
and responsible frame is swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::formWeakReference()
. Did someone else have had similar issue? Is there some way I can fix this?
In Swift, [weak self] prevents closures from causing memory leaks in your application. This is because when you use [weak self], you tell the compiler to create a weak reference to self. In other words, the ARC can release self from memory when necessary.
Using [weak self] is only required within situations in which capturing self strongly would end up causing a retain cycle, for example when self is being captured within a closure that's also ultimately retained by that same object.
“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialisation.”
Try setting the variable instead of being weak
set it to be unowned
.
This is a Swift bug sort of as there is no warning for the developer that he is capturing a strong reference of the nested closure, however, setting it to unowned
should do as a workaround for now.
EDIT1: https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001197.html
Mentioned as an improvement from here here:
class ViewControllerBase: UIViewController {
let timer:DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue(label: "q.q"))
deinit {
NSLog("deinit of \(NSStringFromClass(type(of: self)))")
}
override func viewDidLoad() {
super.viewDidLoad()
timer.scheduleRepeating(deadline: .now(), interval: .seconds(1))
timer.setEventHandler {
UIView.animate(withDuration: 0.2) { [weak self] in
self?.view.backgroundColor = UIColor.green
}
}
}
This leaks memory in a subtle way...there is a retain loop even though self is only used in a "weak" manner. This is because the nested closure captures a strong reference for use in the closure that follows.
EDIT 2:
I might be wrong but the OP is using changes.forEach
closure and then another closure with changes.added.forEach
I could be wrong but this might be the cause of the whole issue perhaps declaring it there [weak self] (cluster, change)
in ... could possibly remove the issue. It is swifts built in closure but still a closure, that could technically cause them to be nested.
Try changing your code to:
changes.forEach{[weak self] (cluster, change) in
see if that helps
or
changes.forEach{[unowned self] (cluster, change) in
Also any chance that you could paste your code instead of doing a screenshot as it is easier to recreate your code instead of retyping it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With