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

[SR-4522] #keyPath broken for isFinished property of Operation in Swift 3.1 #47099

Closed
mattneub opened this issue Apr 7, 2017 · 2 comments
Closed
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@mattneub
Copy link

mattneub commented Apr 7, 2017

Previous ID SR-4522
Radar None
Original Reporter @mattneub
Type Bug
Status Resolved
Resolution Duplicate
Environment

Xcode Version 8.3 (8E162) running on Sierra

Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: af6b518132a5511470360293bde4eb21

duplicates:

  • SR-4397 #keyPath(...) incorrectly resolves paths for Operation state properties

Issue Description:

This UIViewController code worked back in Xcode 8.2, Swift 3:

    let q = OperationQueue()

    override func viewDidLoad() {
        super.viewDidLoad()
        let op = Operation()
        op.addObserver(self, forKeyPath: #keyPath(Operation.isFinished), options: [], context: nil)
        self.q.addOperation(op)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        print(keyPath)
        if let op = object as? Operation, let keyPath = keyPath {
            op.removeObserver(self, forKeyPath: keyPath)
        }
    }

In Xcode 8.3, Swift 3.1, that same code now crashes with "[object] deallocated while key value observers were still registered with it." Our `observeValue` is not being called!

I have not found any way to get `observeValue` to be called for the `finished` / `isFinished` property while using `#keyPath` syntax. The only workaround I have found is to revert to a raw string:

op.addObserver(self, forKeyPath: "isFinished", options: [], context: nil)

That solves the problem from a practical standpoint, but we are forced to give up the yummy goodness of `#keyPath`.

I believe the source of the problem is that there is something odd about NSOperation's `isFinished` KVO-observable property, but I don't know exactly what it is. It seems to have something to do with the `is` prefix. Swift 3.1 now insists on translating `#keyPath(isFinished)` into "finished", which is clever but wrong in the case of NSOperation — you must use a keypath of "isFinished" (even in Objective-C) or the KVO notification won't fire.

@mattneub
Copy link
Author

mattneub commented Apr 7, 2017

See also my https://bugs.swift.org/browse/SR-2415 which is vaguely related. It may be that this new bug is due to an attempt to respond to the earlier bug.

@mattneub
Copy link
Author

mattneub commented Apr 7, 2017

Thanks for the pointer to the duplicate. It is indeed exactly the same.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.
Projects
None yet
Development

No branches or pull requests

1 participant