> On Dec 27, 2015, at 4:23 AM, Tino Heth <[email protected]> wrote:
>
>>
>> Of course, if you’re worried about the performance costs associated with
>> that extra method call, you might want to include a keyword, such as
>> “observable”, and only generate the method call(s) if that keyword is on the
>> property.
> I strongly agree that Swift should have/keep a possibility to create
> properties with no performance penalty — but I guess comfort is more
> important, so I'd rather make observable the default and offer a possibility
> to disable it.
>
> Tino
The problem, as I see it, is that KVO is not useful unless the author has
specifically thought about it, and if “observable” is not the default, but
something that the author of the class had to add, this demonstrates that the
author *has* considered KVO compliance for the property. Without some way to
know that the property has deliberately been made KVO compliant, code that
observes the property cannot be reliable. Therefore, I’d suggest *not* making
observable the default, as it ultimately makes KVO a lot more useful.
Example:
class MyObject {
var foo: Int { get } // This is a computed property, possibly dependent
on something else. Can I safely observe it and expect it to work?
var bar: Int // This is a stored property—but do I know it
won’t be changed to a computed property in the future? Can I observe this and
trust my code won’t break in version 2.0?
}
vs.
class MyObject {
observable var foo: Int { get } // YES I can safely observe this.
observable var bar // YES I can safely observe this.
}
Observing things that aren’t observable is fraught with peril (in the current
Objective-C implementation, it can often lead to crashes via exceptions being
thrown). Knowing that it’s safe is valuable—I’d even say essential. Currently
you have to look in the documentation, which as we all know isn’t always
complete or up to date. Having the keyword there shows, right in the interface,
that the author has committed to making this property compliant and keeping it
that way in future releases.
The observable keyword could also allow one to set the KVO key string to
something other than just the name of the property:
class MyObject {
observable(somethingElse) var something: Int
}
You’d also need an annotation to tell the system which other key paths the
property is dependent upon, which I’d probably do something like this:
class MyObject {
observable var foo: Int
observable var bar: Int {
get { return self.foo }
set(bar) { self.foo = bar }
depends { return [“foo”] }
}
}
The compiler could automatically add a CollectionType property to the class
corresponding to each property, and then rewrite the property setter something
like this (pseudocode):
class MyObject {
private var observersOfFoo: [ObserverProtocol]?
observable var foo: Int {
set(newValue) {
let oldValue = _foo
_foo = newValue // or whatever the default setter
usually does
self.observersOfFoo?.forEach {
$0.notifyKeyValueChanged(self, key: “foo”, oldValue: oldValue) }
}
}
}
I made it optional so that for the common case where there aren’t actually any
observers on the property, the only performance costs are the store of the old
value and checking an optional. Since optionals are basically enums, which are
represented as an 8-bit integer which in this case can have the values 0 or 1,
I’d expect checking an optional to have similar performance characteristics to
checking a boolean, and thus I’d expect it to perform better than checking
whether an array is empty, and doing some quick tests seems to back that up.
Charles
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution