[Discussion] Referencing the Objective-C selector of property getters and setters


(David Hart) #1

As was discussed in a previous thread, here is my proposal for allowing the new #selector syntax to support referencing property getter and setters. Does anybody have any comments before I push the proposal forward?

David.

Referencing the Objective-C selector of property getters and setters

Proposal: TBD
Author(s): David Hart <https://github.com/hartbit>
Status: TBD
Review manager: TBD
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#introduction>Introduction

Proposal SE-0022 <https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md> to reference Objective-C selectors for methods was accepted and implemented. Unfortunately, it does not allow referencing the getter and setter methods of properties. This proposal seeks to provide a design to reference those methods for the Swift 3.0 timeframe.

The idea for this proposal was originally discussed on the following Swift-evolution thread: here <http://article.gmane.org/gmane.comp.lang.swift.evolution/7614>
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#motivation>Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#proposed-solution>Proposed solution

Introduce two new overrides to the #selector expression that allows building a selector which points to the getter or the setter of a property.

class Person: NSObject {
  dynamic var firstName: String
  dynamic let lastName: String
  dynamic var fullName: String {
      return "\(firstName) \(lastName)"
  }

  init(firstName: String, lastName: String) {
    self.firstName = firstName
    self.lastName = lastName
  }
}

let firstNameGetter = #selector(getter: Person.firstName)
let firstNameSetter = #selector(setter: Person.firstName)
Both overrides expect a property and the setter requires a variable property. For example, the following line of code would produce an error because the lastName property is defined with let.

let lastNameSetter = #selector(setter: Person.lastName)
// Argument of #selector(setter:) must refer to a variable property
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#impact-on-existing-code>Impact on existing code

The introduction of the new #selector overrides has no impact on existing code and could improve the string-literal-as-selector to #selector migrator.

<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#alternatives-considered>Alternatives considered

A long term alternive could arrise from the design of lenses in Swift. But as this is purely hypothetical and out of scope for Swift 3, this proposal fixes the need for referencing property selectors in a type-safe way straight-away.


(Chris Lattner) #2

As was discussed in a previous thread, here is my proposal for allowing the new #selector syntax to support referencing property getter and setters. Does anybody have any comments before I push the proposal forward?

+1, proposal LGTM.

-Chris

···

On Feb 24, 2016, at 4:21 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

David.

Referencing the Objective-C selector of property getters and setters

Proposal: TBD
Author(s): David Hart <https://github.com/hartbit>
Status: TBD
Review manager: TBD
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#introduction>Introduction

Proposal SE-0022 <https://github.com/apple/swift-evolution/blob/master/proposals/0022-objc-selectors.md> to reference Objective-C selectors for methods was accepted and implemented. Unfortunately, it does not allow referencing the getter and setter methods of properties. This proposal seeks to provide a design to reference those methods for the Swift 3.0 timeframe.

The idea for this proposal was originally discussed on the following Swift-evolution thread: here <http://article.gmane.org/gmane.comp.lang.swift.evolution/7614>
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#motivation>Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#proposed-solution>Proposed solution

Introduce two new overrides to the #selector expression that allows building a selector which points to the getter or the setter of a property.

class Person: NSObject {
  dynamic var firstName: String
  dynamic let lastName: String
  dynamic var fullName: String {
      return "\(firstName) \(lastName)"
  }

  init(firstName: String, lastName: String) {
    self.firstName = firstName
    self.lastName = lastName
  }
}

let firstNameGetter = #selector(getter: Person.firstName)
let firstNameSetter = #selector(setter: Person.firstName)
Both overrides expect a property and the setter requires a variable property. For example, the following line of code would produce an error because the lastName property is defined with let.

let lastNameSetter = #selector(setter: Person.lastName)
// Argument of #selector(setter:) must refer to a variable property
<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#impact-on-existing-code>Impact on existing code

The introduction of the new #selector overrides has no impact on existing code and could improve the string-literal-as-selector to #selector migrator.

<https://github.com/hartbit/swift-evolution/tree/objc-property-selectors#alternatives-considered>Alternatives considered

A long term alternive could arrise from the design of lenses in Swift. But as this is purely hypothetical and out of scope for Swift 3, this proposal fixes the need for referencing property selectors in a type-safe way straight-away.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #3

Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

···

--
Brent Royal-Gordon
Architechies


(David Hart) #4

In the original thread, my use case was the ability to get type-safety for key-value coding:

david.setValue(30, forKey: String(#selector(getter: Person.age)))

···

On 25 Feb 2016, at 06:50, Brent Royal-Gordon <brent@architechies.com> wrote:

Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

--
Brent Royal-Gordon
Architechies


(Keith Smiley) #5

Another reasonable use case for this is with `UILocalizedIndexedCollation`. For example with Swift 2.1:

let collation = UILocalizedIndexedCollation.currentCollation()
collation.sectionForObject("something", collationStringSelector: "lowercaseString") // NSString.lowercaseString

Currently the Xcode quickfix is:

collation.sectionForObject("something", collationStringSelector: Selector("lowercaseString"))

But I guess ideally this would work something like:

```
collation.sectionForObject("something", collationStringSelector: #selector(NSString.lowercaseString))

···

--
Keith Smiley

On 02/24, Brent Royal-Gordon via swift-evolution wrote:

> Motivation
>
> The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #6

Now that I’m thinking about it, wouldn’t my need be better served by a different proposal for:

#key(Person.firstName) // returns the string “firstName”
#keyPath(Person.mother.firstName) // returns the string “mother.firstName”

How doable is the keyPath version?

···

On 25 Feb 2016, at 08:10, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

In the original thread, my use case was the ability to get type-safety for key-value coding:

david.setValue(30, forKey: String(#selector(getter: Person.age)))

On 25 Feb 2016, at 06:50, Brent Royal-Gordon <brent@architechies.com> wrote:

Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Hart) #7

Wouldn't it be:

#selector(getter: NSString.lowercaseString))

To allow us to disambiguate getters and setters?

···

On 15 Mar 2016, at 06:09, Keith Smiley <keithbsmiley@gmail.com> wrote:

Another reasonable use case for this is with `UILocalizedIndexedCollation`. For example with Swift 2.1:

let collation = UILocalizedIndexedCollation.currentCollation()
collation.sectionForObject("something", collationStringSelector: "lowercaseString") // NSString.lowercaseString

Currently the Xcode quickfix is:

collation.sectionForObject("something", collationStringSelector: Selector("lowercaseString"))

But I guess ideally this would work something like:

```
collation.sectionForObject("something", collationStringSelector: #selector(NSString.lowercaseString))

--
Keith Smiley

On 02/24, Brent Royal-Gordon via swift-evolution wrote:

Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Kashivskyy) #8

I'm +1 on this as well.

Pozdrawiam – Regards,
Adrian Kashivskyy

···

Wiadomość napisana przez David Hart via swift-evolution <swift-evolution@swift.org> w dniu 25.02.2016, o godz. 08:38:

Now that I’m thinking about it, wouldn’t my need be better served by a different proposal for:

#key(Person.firstName) // returns the string “firstName”
#keyPath(Person.mother.firstName) // returns the string “mother.firstName”

How doable is the keyPath version?

On 25 Feb 2016, at 08:10, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

In the original thread, my use case was the ability to get type-safety for key-value coding:

david.setValue(30, forKey: String(#selector(getter: Person.age)))

On 25 Feb 2016, at 06:50, Brent Royal-Gordon <brent@architechies.com> wrote:

Motivation

The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.

What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Keith Smiley) #9

Maybe it would be nice if we preferred getters instead? Since I (making a
totally unfounded assumption) assume that would be used more. But either way, I
just wanted to show a quick example of the problem, I'm personally less worried
about the exact syntax.

···

--
Keith Smiley

On 03/15, David Hart wrote:

Wouldn't it be:

#selector(getter: NSString.lowercaseString))

To allow us to disambiguate getters and setters?

> On 15 Mar 2016, at 06:09, Keith Smiley <keithbsmiley@gmail.com> wrote:
>
> Another reasonable use case for this is with `UILocalizedIndexedCollation`. For example with Swift 2.1:
>
> ```
> let collation = UILocalizedIndexedCollation.currentCollation()
> collation.sectionForObject("something", collationStringSelector: "lowercaseString") // NSString.lowercaseString
> ```
>
> Currently the Xcode quickfix is:
>
> ```
> collation.sectionForObject("something", collationStringSelector: Selector("lowercaseString"))
> ```
>
> But I guess ideally this would work something like:
>
> ```
> collation.sectionForObject("something", collationStringSelector: #selector(NSString.lowercaseString))
>
> --
> Keith Smiley
>
> On 02/24, Brent Royal-Gordon via swift-evolution wrote:
>>> Motivation
>>>
>>> The #selector feature is very useful but does not yet cover all cases. Accessing poperty getter and setters requires to drop down to the string syntax and forgo type-safety. This proposal supports this special case without introducing new syntax, but by introducing new overloads to the #selector compiler expression.
>>
>> What I don't understand is, what's the use case? When you want to access properties dynamically in Objective-C, you usually use key-value coding, not selectors. Can you point to APIs it would be helpful to use this with, or write some realistic code which uses this feature? Or is this basically just completeness for the sake of completeness?
>>
>> --
>> Brent Royal-Gordon
>> Architechies
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution