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

Kevin Ballard kevin at sb.org
Fri Dec 16 00:36:52 CST 2016


On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
>> 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.


No, if you implement keyPathsForValuesAffecting<key>()  then you get
"foo" KVO notifications when "bar" is mutated.  That's the whole
point of that method, and this is exactly what you have to do in Obj-
C as well.


>> 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


That is exceedingly rare. I can't even remember the last time I used
such a thing.


> I know it’s commonplace to use ‘dynamic’ all over the place wherever
> Core Data is involved.


It is? Why? Maybe you're confusing this with Obj-C's @dynamic keyword,
which is completely unrelated to Swift's `dynamic`. When writing Swift
NSManagedObject subclasses, you use the @NSManaged property attribute,
not the `dynamic` keyword (@NSManaged does effectively the same thing
that Obj-C's @dynamic, except it's reserved for integration with
CoreData instead of being as generic as Obj-C's @dynamic is).


> Long story short, ‘dynamic’ does not guarantee KVO conformance in any
> way, shape, or form.


And declaring that your property returns a String doesn't guarantee that
it actually does either. You can always write broken code. But `dynamic`
is required for automatic KVO conformance, and it's extremely rare to
have a reason to use `dynamic` outside of KVO, so it's a really really
strong signal that the property supports KVO. If you're using `dynamic`
on a property but don't support KVO correctly, as you showed in your
code example, that's a bug with your code.


-Kevin Ballard



> 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.


What? No. You marked the property as `dynamic`, which means it'll always
go through message send, which means it'll invoke automatic KVO
conformance and trigger 2 KVO notifications. And you can't mark a
property both `@nonobjc` and `dynamic` as the latter implies the former.


-Kevin Ballard


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


More information about the swift-evolution mailing list