Skip to content
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

Merged
merged 1 commit into from
Sep 4, 2023

Conversation

buggmagnet
Copy link
Contributor

@buggmagnet buggmagnet commented Aug 31, 2023

This change is Reviewable

@buggmagnet buggmagnet requested a review from pronebird August 31, 2023 09:22
@linear
Copy link

linear bot commented Aug 31, 2023

isReadyObserver = observe(\.isReady, options: []) { operation, _ in
operation.checkReadiness()
// Clear the observer when the operation is finished to avoid leaking memory
if operation.state == .finished {
Copy link
Contributor

@pronebird pronebird Aug 31, 2023

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 {
Copy link
Contributor

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?

@pronebird pronebird added the iOS Issues related to iOS label Aug 31, 2023
Copy link
Contributor Author

@buggmagnet buggmagnet left a 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.

@buggmagnet buggmagnet force-pushed the fix-swiftlint-warning-block_based_kvo-ios-258 branch from ebd6a0b to 8254a68 Compare September 4, 2023 09:24
@buggmagnet buggmagnet force-pushed the fix-swiftlint-warning-block_based_kvo-ios-258 branch from 8254a68 to 52c06cb Compare September 4, 2023 09:24
Copy link
Contributor

@pronebird pronebird left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 1 of 1 files at r1, 1 of 1 files at r2.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved

@buggmagnet buggmagnet merged commit 20f755e into main Sep 4, 2023
4 checks passed
@buggmagnet buggmagnet deleted the fix-swiftlint-warning-block_based_kvo-ios-258 branch September 4, 2023 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
iOS Issues related to iOS
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants