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 Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
On Dec 15, 2016, at 4:33 PM, Kevin Ballard <kevin@sb.org> wrote:
On Dec 15, 2016, at 4:35 PM, Kevin Ballard <kevin@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