[swift-evolution] [Pitch] Changing NSObject dispatch behavior

Charles Srstka cocoadev at charlessoft.com
Thu Dec 15 17:01:59 CST 2016


> On Dec 15, 2016, at 4:33 PM, Kevin Ballard <kevin at sb.org> wrote:
> 
> The problem with that code isn't that `dynamic` doesn't work for computed properties. It does; if you mutate the `foo` property, you'll get the KVO notifications. The problem is you have one property that depends on another and you didn't set up the KVO machinery properly using automaticallyNotifiesObservers(forKey:) or automaticallyNotifiesObserversOf<key>() (incidentally in Swift you can write the latter as a `static let`, since that becomes a class method in Obj-C).

You’ll only get the notifications if you mutate ‘foo’ directly. This, however, is fairly useless, because if you are watching ‘foo’, you want to be notified every time the value changes, not just when someone hits one particular accessor. Code relying on observation of ‘foo’ in the example I provided would be prone to breaking in mysterious and possibly horrible ways.

> So yes, `dynamic` by itself doesn't mean that the property supports KVO. But there are very few reasons to use `dynamic` outside of supporting KVO, so it's a pretty good signal that the property does support it. And conversely, not having `dynamic` doesn't mean that it doesn't support KVO, though if it does have manual KVO support using will/didChangeValue(forKey:) then it should be documented as such.

Use of the ‘dynamic’ keyword enables all manner of runtime hackery which someone may be employing. The trick to automatically add KVO conformance to accessors is probably the most common, but it’s hardly the only one. One also might want to declare things ‘dynamic’ when working with Objective-C frameworks not under one’s control which might assume the ability to do metaprogramming on your classes—I know it’s commonplace to use ‘dynamic’ all over the place wherever Core Data is involved. Long story short, ‘dynamic’ does not guarantee KVO conformance in any way, shape, or form.

On Dec 15, 2016, at 4:35 PM, Kevin Ballard <kevin at sb.org> wrote:
> 
> Oops, I mean keyPathsForValuesAffectingValue(forKey:) and keyPathsForValuesAffecting<Key>().
> 
> That said, your code as written actually sends 2 KVO change notices for "bar", and you do still need to implement automaticallyNotifiesObservers… to disable the automatic KVO notice for "bar".

Only when the accessor is called from Objective-C, in which the message-send is *always* dynamic and the presence of the ‘dynamic’ keyword is fairly academic. The example, which was simplified for the purpose of clarity, was to illustrate how things work with respect to Swift’s vtable dispatch system. A real-world example could shut off the automatic notifications, or declare the property as @nonobjc, or similar.

Charles

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161215/7ed7e3ea/attachment.html>


More information about the swift-evolution mailing list