[swift-evolution] [Pitch] Changing NSObject dispatch behavior
Brian King
brianaking at gmail.com
Thu Dec 15 20:43:28 CST 2016
First off, I'm still learning out how to debate at this speed, sorry for
the slow replies!
On Wed, Dec 14, 2016 at 9:32 PM, Kevin Ballard <kevin at sb.org> wrote:
> On Wed, Dec 14, 2016, at 05:54 PM, Brian King wrote:
>
> Obj-C compatibility certainly is one reason to use NSObject, but perhaps a
> bigger reason is because you're subclassing some framework-provided class,
> like UIView or UIViewController. Just because I'm subclassing
> UIViewController doesn't mean I want my controller's API to be subject to
> Obj-C method dispatch unnecessarily.
>
> And even in the cases where I'm subclassing NSObject for Obj-C
> compatibility, that doesn't mean that most of the calls to my object are
> coming from Obj-C. All that means is that at least one place my object is
> used is Obj-C, and 99% of the uses might be Swift. Or if I'm writing a
> library, it might mean that I simply want to preserve Obj-C compatibility
> in case a client wants it, even though I expect my clients to be primarily
> Swift (For example, this is how postmates/PMHTTP is written;
> Obj-C–compatible, but the expectation is most clients will probably be
> Swift).
>
It's interesting, your library has very few non-final methods, because most
of your classes are `final`. it's great to have this option, and as a
result, it is very easy to write performant code. It is very wordy to write
runtime friendly code. I think I value these optimizations less than you,
to me it feels like it's pre-mature optimization, especially given how easy
it is to opt into Static dispatch.
>
> > > Interaction with Obj-C runtime machinery stuff like KVO should be
> opt-in. In Obj-C it's ad-hoc, many classes support it for properties but
> many also don't, and very few properties have their KVO conformance
> documented. I don't view having to mark my properties as `dynamic` to
> participate in KVO to be a problem with Swift but rather a feature. It
> tells the reader that this property supports KVO.
> >
> > This is an interesting point, and it would be an interesting semantic.
> > However in practice, the majority of NSObject code is imported from
> > obj-c, and it's generated interface does not follow this convention.
>
> Just because framework classes don't follow this convention doesn't mean
> it's not a valuable convention to have in code written in Swift. There's a
> lot of things that Swift does better than Obj-C, and that you don't get
> when using an API imported from Obj-C, but that's not a reason to not do
> those things.
>
> > Also, it's strange to conflate how something was dispatched and if it
> > supported KVO. I think property delegates will be the future here and
> > enable some exciting contracts if adopted.
> >
> > Another approach is to just make it easier to opt into the full obj-c
> > machinery. The addition of a class or extension level `dynamic`
> > keyword would be great. If we could get buy in on this, then the
> > debate becomes if NSObject should default to `dynamic` or not.
>
> I don't think we should ever make it possible to mark an entire class as
> `dynamic`. This just reintroduces the Obj-C problem, where many properties
> support KVO, but not all, and there's no indication on the property itself
> as to whether it supports it.
>
This would just be short hand for adding the `dynamic` keyword in front of
every variable and method, so shy of the already existing computed property
getter case, all of the properties should just work.
> -Kevin Ballard
>
> > Brian
> >
> > >
> > > -Kevin Ballard
> > >
> > > On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution
> wrote:
> > >> I wanted to follow up to a blog post I wrote about Message Dispatch in
> > >> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> > >> mentioned some changes to NSObject that didn’t result in any
> > >> objections, so I thought it was time to see what the SE mailing list
> > >> thought.
> > >>
> > >> I’ve read a few conversations on SE mailing list that have morphed
> > >> into abstract conversations about dynamic vs static dispatch. I want
> > >> to focus specifically on how Swift NSObject subclasses behave.
> > >>
> > >> I think that there are 2 changes that will result in fewer bugs and
> > >> will not have a substantial impact on performance:
> > >>
> > >>
> > >> ## Remove Table Dispatch from NSObject
> > >>
> > >> NSObject subclasses use table dispatch for the initial class
> > >> declaration block. I think that using message dispatch for NSObject
> > >> subclasses everywhere will result in a much more consistent developer
> > >> experience.
> > >>
> > >> ## Block NSObject Visibility Optimizations
> > >>
> > >> Swift upgrades method dispatch to final when the compiler can prove
> > >> that the method is not subclassed. I would like to see Swift be more
> > >> careful about the impact of these optimizations on message dispatch,
> > >> and consider message dispatch non-upgradable.
> > >>
> > >>
> > >> I thought it would help to frame this choice as a trade-off between
> > >> Swift’s goals of safe, fast, and expressive.
> > >>
> > >> ## Safe
> > >>
> > >> Always using message dispatch for NSObject subclasses will fix a class
> > >> of runtime errors in framework features that are designed around
> > >> message passing (e.g. KVO). Arguments against using dynamic features
> > >> like this are valid, but Cocoa frameworks still use dynamic features
> > >> and the above behaviors result in actual bugs. As a bonus, this will
> > >> resolve SR-584, where a table-dispatched method that is overridden by
> > >> a message dispatch method doesn’t behave correctly.
> > >>
> > >> ## Fast
> > >>
> > >> The above changes will result in slower dispatch in NSObject
> > >> subclasses. However, I don't think that these dispatch changes
> > >> actually have a tangible impact on performance. Most NSObject
> > >> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
> > >> specific hot spot, it would still be optimizable via the final
> > >> keyword.
> > >>
> > >> ## Expressive
> > >>
> > >> Using table dispatch for NSObject without any source indication or
> > >> library documentation is not very expressive. I think it’s important
> > >> to weigh table dispatch behavior against all of the framework
> > >> documentation and developer experience that assume message dispatch.
> > >> This will also eliminate the need for a lot of `@objc` and `dynamic`
> > >> annotations that are often inconsistently applied depending on if they
> > >> are needed in the scope they are defined in (e.g. class vs extension).
> > >>
> > >>
> > >> If this idea shows promise, I’d be glad to formalize a Swift Evolution
> > >> Proposal and explore syntactic details. I think being able to flag a
> > >> class with `dynamic` and applying this flag to `NSObject` may be the
> > >> only syntactic change needed. However, it would be good to debate the
> > >> merit of the behavior change before the syntax.
> > >>
> > >>
> > >> Thanks!
> > >>
> > >>
> > >> Brian King
> > >> _______________________________________________
> > >> swift-evolution mailing list
> > >> swift-evolution at swift.org
> > >> https://lists.swift.org/mailman/listinfo/swift-evolution
> > > _______________________________________________
> > > swift-evolution mailing list
> > > swift-evolution at swift.org
> > > https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161215/1a2242d5/attachment.html>
More information about the swift-evolution
mailing list