On Mon, Feb 27, 2017 at 5:35 PM Zach Waldowski via swift-evolution < swift-evolution@swift.org> wrote:
I don't understand the question. It should turn it into a group of
NSStrings prefixed by a common name. That's how they're imported from
Objective-C, stripped of their common prefix.
Sincerely,
Zachary Waldowski
zach@waldowski.me
On Mon, Feb 27, 2017, at 05:02 PM, Derrick Ho via swift-evolution wrote:
NS_EXTENSIBLE_STRING_ENUM
Turns a groups of NSStrings into a struct.
What do you suggest for the reverse?
On Mon, Feb 27, 2017 at 4:39 PM Zach Waldowski via swift-evolution < > swift-evolution@swift.org> wrote:
-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
zach@waldowski.me
On Sun, Feb 26, 2017, at 01:21 PM, Derrick Ho via swift-evolution wrote:
I updated my proposal
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md>
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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-filename.md>
- Authors: Derrick Ho <https://github.com/wh1pch81n>
- Review Manager: TBD
- Status: Awaiting review
*During the review process, add the following fields as needed:*
- Decision Notes: Rationale
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161114/028950.html>
- Previous Proposal: SE-0033
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/0033-import-objc-constants.md>
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#introduction>
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
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161114/028950.html>
Discussion
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170220/032656.html>
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#motivation>
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
<https://bugs.swift.org/browse/SR-3146>\.
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.
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#proposed-solution>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.
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#detailed-design>Detailed
design
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-string-enum---casestring-translations>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-string-enum---failable-initializer>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-string-enum---methods>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-struct-string---string-translations>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-struct-string---non-failable-initializer>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-struct-string---extension>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#swift-string-enum--swift-struct-string---equalityhashrawvalue>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#objective-c-name>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
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#source-compatibility>Source
compatibility
This will be an additive feature and will not break anything existing.
<https://github.com/wh1pch81n/swift-evolution/blob/swift-enum-objc/proposals/NNNN-Swift-enum-strings-ported-to-Objective-c.md#alternatives-considered>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 <wh1pch81n@gmail.com> 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 <milseman@apple.com> > 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-evolution@swift.org> 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
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
_______________________________________________
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
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution