-1 as written due to the impedance mismatch with importing NS_STRING_ENUM and NS_EXTENSIBLE_STRING_ENUM. Exporting to Objective-C should export a typedef and several constants, not a class. Exporting generated accessors to Objective-C is unnecessary as you have -isEqual: and -hashValue on NSString over there.
I'm not sure how technically feasible it is to identify "a struct with a single field conforming to RawRepresentable" to make it compatible with @objc, though I'm not really a compiler person. Other than that, I like the idea. I don't believe any of the annotations to make Objective-C code better in Swift should be one-way. Sincerely, Zachary Waldowski [email protected] On Sun, Feb 26, 2017, at 01:21 PM, Derrick Ho via swift-evolution wrote: > I updated my proposal[1] to reflect the community's desire to build on > @objc instead of adding a new attribute @objcstring. > > I've included it below for convenience: > > Swift Enum strings ported to Objective-c > * Proposal: SE-NNNN[2] > * Authors: Derrick Ho[3] > * Review Manager: TBD > * Status: Awaiting review > *During the review process, add the following fields as needed:* > * Decision Notes: Rationale[4] > * Previous Proposal: SE-0033[5] > Introduction > We should allow swift-enum-strings and swift-struct-strings to be > bridged to objective-c. We can use the following notation: > @objc enum Planets: String { case Mercury } > @objc struct Food: String { public static let hamburger = > Food(rawValue: "hamburger") } > Creating a bridgable version will allow objective-c to enjoy some of > the benefits that swift enjoys. > Swift-evolution thread: Discussion[6] Discussion[7] > Motivation > NS_STRING_ENUM and NS_EXSTENSIBLE_STRING_ENUM are annotations that you > can add to an objective-c global string. The annotations will make > swift interpret the objective-c global strings as enum and structs > respectively in theory. But it actually doesn't ever create enums[8]. > The problem seems to stem from the conversion from objc to swift. It > might be more fruitful to make a conversion from swift to objc. > However, what if we take it a step further? Turning a swift-string- > enum into a bunch of global NSStrings really limits its power. There > are many classes written by apple that are structs in swift but > become classes in objective-c (i.e. String becomes NSString, Date > becomes NSDate, Array becomes NSArray, etc). There is a special > bridging mechanism that allows this to be possible. I think we should > expand on that. > Proposed solution > // `@objc` and `String` can be applied to an enum to make it available > to objective-c: // @objc public enum Food: String { case Calamari case > Fish } // This can be ported over to Objective-c as an objective-c > class @interface Food: NSObject @property (readonly) NSString > *_Nonnull rawValue; - (instancetype > _Nullable)initWithRawValue:(NSString *_Nonnull)rawValue; + > (instanceType _Nonnull)Calamari; + (instanceType _Nonnull)Fish; @end > > // `@objc` and `String` can be applied to a struct to make it > available to objective-c: // @objc public struct Planets: String { > public let rawValue: String //<- This should be implicit and the user > should not need to add it init(rawValue: String) { self.rawValue = > rawValue } //<- This should be implicit and the user should not need > to add it public static let Earth = Planets(rawValue: "Earth") //<- > user defines these public static let Venus = Planets(rawValue: > "Venus") //<- user defines these } // This can be ported over to objective- > c as a class @interface Planets: NSObject - (instancetype > _Nonnull)initWithRawValue:(NSString *_Nonnull)rawValue; + > (instancetype)Earth; + (instancetype)Venus; @end > > The difference between a swift-enum-string and a swift-struct-string > is that swift-enum-string provides a failable initializer while swift-struct- > string provides a non-failable initializer. > Detailed design > swift-string-enum - case/string translations > A swift-enum-string, is created with cases and it has an implicit > string value based on the name of the case. The user may also add a > name that does not equal the name of the case. > // Swift @objc public enum Food: String { case Calamari case Fish = > "Flounder" //<-- User wants Fish to be Flounder } // Objective-c > @interface Food: NSObject @property (readonly) NSString *_Nonnull > rawValue; + (instanceType _Nonnull)Calamari; + (instanceType > _Nonnull)Fish; @end @implementation Food + (instanceType > _Nonnull)Calamari { return [[Food alloc] > initWithRawValue:@"Calimari"]; } + (instanceType _Nonnull)Fish { > return [[Food alloc] initWithRawValue:@"Flounder"]; } //<-- Fisher > contains Flounder @end > > swift-string-enum - failable initializer > A swift-enum-string has the ability to be initialized with a string. > If the string matches one of the possible cases, then it returns it, > otherwise it will return nil. This feature might be implemented as a > dictionary or some other means that gets the same results; Below is my > suggestion. > // Assuming this swift implementation @objc public enum Food: String { > case Calamari case Fish = "Flounder" //<-- User wants Fish to be > Flounder } // The objective-c failable initializer may look like > this. @implementation Food - (instancetype > _Nullable)initWithRawValue:(NSString *_Nonnull)rawValue { static > NSDictionary <NSString *, NSString *>*states; if (!states) { // A > dictionary where the KEYs are the acceptable rawValue's and the VALUE > are empty strings states = @{ @"Calimari" : @"", @"Flounder" : @"" } } > if ((self = [super init])) { if (states[rawValue]) { _rawValue = > rawValue return self; } } return nil; } @end > > swift-string-enum - methods > swift enums allow methods to be defined. If you mark a method with > @objc it should be made available to objective-c. > // Swift @objc public enum Food: String { case Calamari case Fish > @objc func price() -> Double { // ... } } // Objective-c @interface > Food: NSObject // ... - (Double)price; // ... @end > > swift-struct-string - string translations > A swift-struct-string needs to be marked with @objc and inherit from > String to bridge to objective-c. A property or method must be marked > with @objc to be made available to objective-c. > // Swift @objc struct Planet { @objc public static let Earth = > Planet(rawValue: "Earth") @objc public func distanceFromSun() -> > Double { ... } } // Objective-c @interface Planet + (instancetype > _Nonnull)Earth; + (Double)distanceFromSun; @end > > swift-struct-string - non-failable initializer > The swift-struct-string initializer should not be failable and will > accept any string value > @implementation Planet - (instancetype > _Nonnull)initWithRawValue:(NSString *)rawValue { if ((self = [super > init])) { _rawValue = rawValue; } return self; } @end > > swift-struct-string - extension > One of the key attributes of an extensible string enum is that it > can be extended. This should produce something available to objective- > c. The original definition of Planet needs to have been marked > with @objc. > // Swift extension Planet { @objc public static let Pluto = > Planet(rawValue: "Pluto") } // Objective-c @interface Planet > (extention_1) - (instancetype _Nonnull)Pluto; @end @implementation > Planet (extention_1) - (instancetype _Nonnull)Pluto { return [[Planet > alloc] initWithRawValue:@"Pluto"]; } @end > > swift-string-enum && swift-struct-string - equality/hash/rawValue > When an enum or struct is marked with @objc and String, the objective- > c class that is produced should have its equality/hash methods and > rawValue property implicitly be implemented. The user should not need > to implement these on his/her own. > @implementation Food - (instancetype)rawValue { return _rawValue; } > - (NSUInteger)hash { return [[self rawValue] hash]; } - > (BOOL)isEqual:(id)object { if (self == object) { return YES } if > (![object isKindOfClass:[Food class]]) { return NO; } return > [self.rawValue isEqualToString:((Food *)object).rawValue]; } @end > > Objective-c name > In the above examples, the objective-c name of the class and the swift > name of the class were the same. If this causes a naming conflict then > the objective-c name could be Prefixed with ENUM. > // Swift @objc enum Planet: String { ... } // Objective-c @interface > ENUMPlanet @end > > The programmer should still be able to add their own name by > specifying it as an argument. > // Swift @objc(CustomPlanet) enum Planet { ... } // Objective-c > @interface CustomPlanet @end > > Source compatibility > This will be an additive feature and will not break anything existing. > Alternatives considered > * Implement a swift class that implements the above described > behviors. > * Don't change anything. > > On Tue, Feb 21, 2017 at 6:09 PM Derrick Ho > <[email protected]> wrote: >> True. >> In my proposal I mention how NS_STRING_ENUM doesn't produce an >> swift enum. >> >> So one solution is to merely "go the other way" which would produce >> what Kevin N. suggested. >> >> Is it not odd that that the objc version is so different from the >> swift version? >> >> Would it not be better to offer a somewhat similar API experience >> between the two languages? >> >> @objcstring would "promote" the swift enum to an objective-c class to >> make the API experience similar. >> >> I understand that maybe @objcstring is too niche to get its own >> annotation. Instead @objc should become more powerful. >> >> I think @objc should make an enum become a class with swift-enum like >> abilities. This would allow enum functions to be bridged over to objective- >> c as well. >> On Tue, Feb 21, 2017 at 1:32 PM Michael Ilseman >> <[email protected]> wrote: >>> A quick note addressing a misconception that you’ll want to clean up >>> for a formal proposal: >>> >>> NS_[EXTENSIBLE_]STRING_ENUMs both generate Swift structs, the >>> difference is only in the explicitness of the rawValue initializer. >>> To use the “other direction” analogy, you’d similarly want them to >>> apply for rawValue-ed structs alone. The reasons are the same: only >>> the structs are layout-compatible because enums are integers. >>> >>> Once you go down this route, perhaps it doesn’t make sense to >>> annotate the struct decls themselves anymore. Maybe you just want >>> more @objc control over bridging the types. For example, maybe you >>> want to introduce a feature so that static members that are layout- >>> compatible with String are bridged as global strings with the >>> supplied name. >>> >>> >>> >>>> >>>> On Feb 20, 2017, at 4:07 PM, Derrick Ho via swift-evolution <swift- >>>> [email protected]> wrote: >>>> Swift should not forsake objective-c. At least not when it comes >>>> enum strings. Although swift enums are suppose to be swift only, I >>>> think we should add a new attribute to slightly relax that. I >>>> think a good attribute would be @objcstring. >>>> >>>> By adding @objcstring, an objective-c exclusive class will be >>>> generated. >>>> >>>> @objcstring >>>> enum Planet { >>>> case Jupiter >>>> } >>>> >>>> I have written up a proposal with more details on what it would >>>> look for objective-c. >>>> >>>> https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md >>>> >>>> If no one objects to this proposal I'll submit it. >>>> >>>> **notes: I am reviving this discussion so that I may submit this >>>> for Swift 4 stage 2 >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] >>>> https://lists.swift.org/mailman/listinfo/swift-evolution > _________________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution Links: 1. https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md 2. https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-filename.md 3. https://github.com/wh1pch81n 4. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161114/028950.html 5. https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/0033-import-objc-constants.md 6. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161114/028950.html 7. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032656.html 8. https://bugs.swift.org/browse/SR-3146
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
