> 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

Reply via email to