[swift-evolution] Proposal: Change Obj-C name for nested types to include enclosing types

Jordan Rose jordan_rose at apple.com
Thu Dec 10 18:48:25 CST 2015


My point is that Swift currently treats @objc on nested types differently based on whether the outer type is @objc—if the outer type is @objc, the inner types end up in the generated header; otherwise they don't. And what about @objc on local types?

(Right now we have a hole: an API using an @objc type will show up in the generated header, but the type may not, leading to errors in the header. We should resolve that somehow.)

Jordan


> On Dec 9, 2015, at 21:36, Kevin Ballard <kevin at sb.org> wrote:
> 
> We already default nested types to @nonobjc (hence the explicit @objc in my sample). I like that Swift supports using @objc on nested types, because that way I can avoid having to uglify my Swift API just for the sake of Obj-C compatibility (I know I can use a typealias inside the outer type to provide a convenient shorthand for the formerly-nested type, but I still consider that ugly).
> 
> -Kevin
> 
> On Wed, Dec 9, 2015, at 06:03 PM, Jordan Rose wrote:
>> I would rather just not print nested types in the generated header. We already don't do so if the enclosing type is not Objective-C-compatible.
>> 
>> Jordan
>> 
>> 
>>> On Dec 9, 2015, at 15:24, Kevin Ballard via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> When exposing some type to Obj-C, if the type is nested within another type, the Obj-C name should include the enclosing types.
>>> 
>>> For example:
>>> 
>>> class Foo: NSObject {
>>>   @objc enum Bar: Int {
>>>       case One, Two
>>>   }
>>>   @objc class Baz: NSObject {}
>>> }
>>> 
>>> is currently exported to Swift as
>>> 
>>> SWIFT_CLASS("_TtC7unnamed3Foo")
>>> @interface Foo : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> typedef SWIFT_ENUM(NSInteger, Bar) {
>>> BarOne = 0,
>>> BarTwo = 1,
>>> };
>>> 
>>> SWIFT_CLASS("_TtCC7unnamed3Foo3Baz")
>>> @interface Baz : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> I think it should be exported instead as
>>> 
>>> SWIFT_CLASS("_TtC7unnamed3Foo")
>>> @interface Foo : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> typedef SWIFT_ENUM(NSInteger, FooBar) {
>>> FooBarOne = 0,
>>> FooBarTwo = 1,
>>> };
>>> 
>>> SWIFT_CLASS("_TtCC7unnamed3Foo3Baz")
>>> @interface FooBaz : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> This is because the Obj-C declarations are all at the top level (as Obj-C does not have nested types), so a type that is clearly unambiguous in Swift may become ambiguous in Obj-C. As a trivial example, the following Swift code:
>>> 
>>> class Foo: NSObject {
>>>   @objc enum Bar: Int {
>>>       case One, Two
>>>   }
>>> }
>>> 
>>> class Baz: NSObject {
>>>   @objc enum Bar: Int {
>>>       case Apple, Orange
>>>   }
>>> }
>>> 
>>> is currently exported to Obj-C as:
>>> 
>>> SWIFT_CLASS("_TtC7unnamed3Baz")
>>> @interface Baz : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> typedef SWIFT_ENUM(NSInteger, Bar) {
>>> BarApple = 0,
>>> BarOrange = 1,
>>> };
>>> 
>>> SWIFT_CLASS("_TtC7unnamed3Foo")
>>> @interface Foo : NSObject
>>> - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
>>> @end
>>> 
>>> typedef SWIFT_ENUM(NSInteger, Bar) {
>>> BarOne = 0,
>>> BarTwo = 1,
>>> };
>>> 
>>> This is attempting to redefine the type Bar, which is of course problematic.
>>> 
>>> -Kevin Ballard
>>> _______________________________________________
>>> 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/20151210/b6c171e5/attachment.html>


More information about the swift-evolution mailing list