-
Notifications
You must be signed in to change notification settings - Fork 349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use the block based KVO API in AsyncOperation #5077
Conversation
ios/Operations/AsyncOperation.swift
Outdated
isReadyObserver = observe(\.isReady, options: []) { operation, _ in | ||
operation.checkReadiness() | ||
// Clear the observer when the operation is finished to avoid leaking memory | ||
if operation.state == .finished { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like observation API does not maintain a strong reference to target anymore. Try this in playground:
class MyOperation: Operation {
private var observer: NSKeyValueObservation?
override init() {
super.init()
observer = observe(\.isReady, changeHandler: { op, _ in
print(op)
})
}
deinit {
print("deinit!")
}
}
var op: MyOperation? = MyOperation()
op = nil
print("done")
@@ -117,7 +117,7 @@ open class AsyncOperation: Operation { | |||
_error | |||
} | |||
|
|||
override public final var isReady: Bool { | |||
dynamic override public final var isReady: Bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any particular reason why that has to be marked dynamic
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 1 files reviewed, 2 unresolved discussions (waiting on @pronebird)
ios/Operations/AsyncOperation.swift
line 120 at r1 (raw file):
Previously, pronebird (Andrej Mihajlov) wrote…
Any particular reason why that has to be marked
dynamic
?
It's to force dynamic dispatching via the ObjC runtime which is required for KVO to work
Technically it has to be marked both @objc
and dynamic
but we inherit from NSObject
so all our properties are already inherently @objc
This article shows an example on how to do it
ios/Operations/AsyncOperation.swift
line 249 at r1 (raw file):
Previously, pronebird (Andrej Mihajlov) wrote…
It looks like observation API does not maintain a strong reference to target anymore. Try this in playground:
class MyOperation: Operation { private var observer: NSKeyValueObservation? override init() { super.init() observer = observe(\.isReady, changeHandler: { op, _ in print(op) }) } deinit { print("deinit!") } } var op: MyOperation? = MyOperation() op = nil print("done")
I was under that impression too, but I used Instruments to make sure we were not leaking memory, and without that it would leak memory for each operation created.
You can run the check yourself if you want, remove the operation.isReadyObserver = nil
line and run under instruments to see the result.
ebd6a0b
to
8254a68
Compare
8254a68
to
52c06cb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r1, 1 of 1 files at r2.
Reviewable status: complete! all files reviewed, all discussions resolved
This change is