[swift-evolution] [Proposal draft] Referencing the Objective-C selector of a method

Andrew Bennett cacoyi at gmail.com
Mon Jan 11 17:21:03 CST 2016

I agree on pretty much every point. I also saw the light on _ since writing
that :)


On Tue, Jan 12, 2016 at 9:04 AM, Douglas Gregor <dgregor at apple.com> wrote:

> On Jan 11, 2016, at 1:58 PM, Andrew Bennett <cacoyi at gmail.com> wrote:
> Sounds good to me, much nicer than the current approach.
> Perhaps it should be @selector() instead? I don't think you can currently
> get enough information from the type signature alone to differentiate one
> selector from another. This will probably have to introduce new syntax, it
> would require changes to the language not just a standard library function.
> @selector seems to differentiate it from standard structures and functions.
> @ is for attributes, so that doesn’t work. I’ll add commentary to the
> proposal, since this keeps coming up.
> I also think the underscore should be removed, that's outside the scope of
> this proposal though?
> I’m strongly opposed to doing it only for this syntax. Doing it globally
> is annoying, because it requires changes in Clang as well.
> I had concerns for this with Self and associated type requirements,
> however I don't think they're an issue unless Objective-C supports them, or
> this is to be used outside of Objective-C.
> I don’t see this as being a problem now or in the future.
> For the same reasons I'm guessing there's no need for this to distinguish
> between selectors with different return types?
> One can introduce type context (with “as”) if this actually comes up. It
> should be *extremely* rare with Objective-C methods.
> - Doug
> On Tue, Jan 12, 2016 at 8:08 AM, Douglas Gregor via swift-evolution <
> swift-evolution at swift.org> wrote:
>> Here’s a follow-up to the idea I posted for a simple expression to
>> produce the selector for a given method, revised based on the discussion
>> there. The proposal is over at
>> https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md
>> Referencing the Objective-C selector of a method
>>    - Proposal: SE-NNNN
>>    <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-objc-selectors.md>
>>    - Author(s): Doug Gregor <https://github.com/DougGregor>
>>    - Status: *Awaiting review*
>>    - Review manager: TBD
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#introduction>
>> Introduction
>> In Swift 2, Objective-C selectors are written as string literals (e.g.,
>> "insertSubview:aboveSubview:") in the type context of a Selector. This
>> proposal seeks to replace this error-prone approach with Selector initialization
>> syntax that refers to a specific method via its Swift name.
>> Swift-evolution thread: here
>> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/1384/focus=1403>
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#motivation>
>> Motivation
>> The use of string literals for selector names is extremely error-prone:
>> there is no checking that the string is even a well-formed selector, much
>> less that it refers to any known method, or a method of the intended class.
>> Moreover, with the effort to perform automatic renaming of Objective-C
>> APIs
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md>,
>> the link between Swift name and Objective-C selector is non-obvious. By
>> providing explicit "create a selector" syntax based on the Swift name of a
>> method, we eliminate the need for developers to reason about the actual
>> Objective-C selectors being used.
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#proposed-solution>Proposed
>> solution
>> Introduce Selector initialization syntax that allows one to build a
>> selector from a reference to a method, e.g.,
>> control.sendAction(Selector(MyApplication.doSomething), to: target, forEvent: event)
>> where “doSomething” is a method of MyApplication, which might even have a
>> completely-unrelated name in Objective-C:
>> extension MyApplication {
>>   @objc(jumpUpAndDown:)
>>   func doSomething(sender: AnyObject?) { … }
>> }
>> By naming the Swift method and having the Selector initializer do the
>> work to form the Objective-C selector, we free the developer from having to
>> do the naming translation manually and get static checking that the method
>> exists and is exposed to Objective-C.
>> This proposal composes with the Naming Functions with Argument Labels
>> proposal
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160111/006262.html>,
>> which lets us name methods along with their argument labels, e.g.:
>> let sel = Selector(UIView.insertSubview(_:at:)) // produces the Selector "insertSubview:atIndex:"
>> With the introduction of the Selector syntax, we should deprecate the
>> use of string literals to form selectors. Ideally, we could perform the
>> deprecation in Swift 2.2 and remove the syntax entirely from Swift 3.
>> Additionally, we should introduce specific migrator support to translate
>> string-literals-as-selectors into method references. Doing this well is
>> non-trivial, requiring the compiler/migrator to find all of the
>> declarations with a particular Objective-C selector and determine which one
>> to reference. However, it should be feasible, and we can migrator other
>> references to a specific, string-based initialization syntax (e.g.,
>> Selector("insertSubview:atIndex:")).
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#detailed-design>Detailed
>> design
>> The proposed Selector initializer "almost" has the signature:
>> extension Selector {
>>   init<T, U>(_ fn: (T) -> U)
>> }
>> with some additional semantic restrictions that require that input be a
>> reference to an objc method. Specifically, the input expression must be
>> a direct reference to an Objective-C method, possibly parenthesized and
>> possible with an "as" cast (which can be used to disambiguate same-named
>> Swift methods). For example, here is a "highly general" example:
>> let sel = Selector(((UIKit.UIView.insertSubview(_:at:)) as (UIView) -> (UIView, Int) -> Void))
>> The actual implementation will introduce some magic in the type checker
>> to only support references to methods within the Selector initialization
>> syntax.
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#impact-on-existing-code>Impact
>> on existing code
>> The introduction of the Selector initialization syntax has no impact on
>> existing code. However, deprecating and removing the
>> string-literal-as-selector syntax is a source-breaking change. We can
>> migrate the uses to either the new Selectorinitialization syntax or to
>> explicit initialization of a Selector from a string.
>> <https://github.com/DougGregor/swift-evolution/blob/objc-selectors/proposals/0000-objc-selectors.md#alternatives-considered>Alternatives
>> considered
>> The primary alternative is type-safe selectors
>> <https://lists.swift.org/pipermail/swift-evolution/2015-December/000233.html>,
>> which would introduce a new "selector" calling convetion to capture the
>> type of an @objc method, including its selector. One major benefit of
>> type-safe selectors is that they can carry type information, improving type
>> safety. From that discussion, referencing MyClass.observeNotification would
>> produce a value of type:
>> @convention(selector) (MyClass) -> (NSNotification) -> Void
>> Objective-C APIs that accept selectors could provide type information
>> (e.g., via Objective-C attributes or new syntax for a typed SEL),
>> improving type safety for selector-based APIs. Personally, I feel that
>> type-safe selectors are a well-designed feature that isn't worth doing: one
>> would probably not use them outside of interoperability with existing
>> Objective-C APIs, because closures are generally preferable (in both Swift
>> and Objective-C). The cost of adding this feature to both Swift and Clang
>> is significant, and we would also need adoption across a significant number
>> of Objective-C APIs to make it worthwhile. On iOS, we are talking about a
>> relatively small number of APIs (100-ish), and many of those have
>> blocks/closure-based variants that are preferred anyway. Therefore, we
>> should implement the simpler feature in this proposal rather than the far
>> more complicated (but admittedly more type-safe) alternative approach.
>> - Doug
>> _______________________________________________
>> 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/20160112/780230e9/attachment.html>

More information about the swift-evolution mailing list