How to make a Swift String enum available in Objective-C?
From the Xcode 6.3 release notes (emphasis added):
Swift Language Enhancements
...
Swift enums can now be exported to Objective-C using the @objc
attribute. @objc enums must declare an integer raw type, and cannot be
generic or use associated values. Because Objective-C enums are not
namespaced, enum cases are imported into Objective-C as the
concatenation of the enum name and case name.
How to make a Swift enum available in Objective-C?
You can use only Enums witch can be represented in objc:
- Enums without nested enums
- Enums without parameters
- Enums raw types
should be integer
Therefore you can only create another enum, witch can be represented in objc and just add method to convert to it:
public enum TrackingValue {
...
func toObjc() -> ObjcEnum {
...
}
}
and create somewhere swift method to another side:
func convert(_ type: ObjcEnum) -> TrackingValue {
...
}
How to get the name of enumeration value in Swift?
As of Xcode 7 beta 5 (Swift version 2) you can now print type names and enum cases by default using print(_:)
, or convert to String
using String
's init(_:)
initializer or string interpolation syntax. So for your example:
enum City: Int {
case Melbourne = 1, Chelyabinsk, Bursa
}
let city = City.Melbourne
print(city)
// prints "Melbourne"
let cityName = "\(city)" // or `let cityName = String(city)`
// cityName contains "Melbourne"
So there is no longer a need to define & maintain a convenience function that switches on each case to return a string literal. In addition, this works automatically for any enum, even if no raw-value type is specified.
debugPrint(_:)
& String(reflecting:)
can be used for a fully-qualified name:
debugPrint(city)
// prints "App.City.Melbourne" (or similar, depending on the full scope)
let cityDebugName = String(reflecting: city)
// cityDebugName contains "App.City.Melbourne"
Note that you can customise what is printed in each of these scenarios:
extension City: CustomStringConvertible {
var description: String {
return "City \(rawValue)"
}
}
print(city)
// prints "City 1"
extension City: CustomDebugStringConvertible {
var debugDescription: String {
return "City (rawValue: \(rawValue))"
}
}
debugPrint(city)
// prints "City (rawValue: 1)"
(I haven't found a way to call into this "default" value, for example, to print "The city is Melbourne" without resorting back to a switch statement. Using \(self)
in the implementation of description
/debugDescription
causes an infinite recursion.)
The comments above String
's init(_:)
& init(reflecting:)
initializers describe exactly what is printed, depending on what the reflected type conforms to:
extension String {
/// Initialize `self` with the textual representation of `instance`.
///
/// * If `T` conforms to `Streamable`, the result is obtained by
/// calling `instance.writeTo(s)` on an empty string s.
/// * Otherwise, if `T` conforms to `CustomStringConvertible`, the
/// result is `instance`'s `description`
/// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`,
/// the result is `instance`'s `debugDescription`
/// * Otherwise, an unspecified result is supplied automatically by
/// the Swift standard library.
///
/// - SeeAlso: `String.init<T>(reflecting: T)`
public init<T>(_ instance: T)
/// Initialize `self` with a detailed textual representation of
/// `subject`, suitable for debugging.
///
/// * If `T` conforms to `CustomDebugStringConvertible`, the result
/// is `subject`'s `debugDescription`.
///
/// * Otherwise, if `T` conforms to `CustomStringConvertible`, the result
/// is `subject`'s `description`.
///
/// * Otherwise, if `T` conforms to `Streamable`, the result is
/// obtained by calling `subject.writeTo(s)` on an empty string s.
///
/// * Otherwise, an unspecified result is supplied automatically by
/// the Swift standard library.
///
/// - SeeAlso: `String.init<T>(T)`
public init<T>(reflecting subject: T)
}
See the release notes for info about this change.
Is it possible to use Swift's Enum in Obj-C?
As of Swift version 1.2 (Xcode 6.3) you can. Simply prefix the enum declaration with @objc
@objc enum Bear: Int {
case Black, Grizzly, Polar
}
Shamelessly taken from the Swift Blog
Note: This would not work for String enums or enums with associated values. Your enum will need to be Int-bound
In Objective-C this would look like
Bear type = BearBlack;
switch (type) {
case BearBlack:
case BearGrizzly:
case BearPolar:
[self runLikeHell];
}
Objc visible string enum but not RawRepresentable
Swift Language Enhancements
... Swift enums can now be exported to Objective-C using the @objc
attribute. @objc enums must declare an integer raw type, and cannot be
generic or use associated values. Because Objective-C enums are not
namespaced, enum cases are imported into Objective-C as the
concatenation of the enum name and case name.
Above From Xcode 6.4 Release Notes
For this purpose you define the values in Objective-C, you can use the NS_TYPED_ENUM
macro to import constants in Swift
For example:
.h file
typedef NSString *const ProgrammingLanguage NS_TYPED_ENUM;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageSwift;
FOUNDATION_EXPORT ProgrammingLanguage ProgrammingLanguageObjectiveC;
.m file
ProgrammingLanguage ProgrammingLanguageSwift = @"Swift";
ProgrammingLanguage ProgrammingLanguageObjectiveC = @"ObjectiveC";
In Swift, this is imported as a struct as such:
struct ProgrammingLanguage: RawRepresentable, Equatable, Hashable {
typealias RawValue = String
init(rawValue: RawValue)
var rawValue: RawValue { get }
static var swift: ProgrammingLanguage { get }
static var objectiveC: ProgrammingLanguage { get }
}
Although the type is not bridged as an enum, it feels very similar to one when using it in Swift code.
You can read more about this technique in the "Interacting with C APIs" of the Using Swift with Cocoa and Objective-C documentation
Objective-C enum in Swift
These get translated to
countDirection.Up
countDirection.Count
Swift removes as many letters as possible that the enum values have in common with the enumeration name. In your case, with an enumeration called countDirection and a value countDirectionUp, the whole "countDirection" is removed. It's not needed because you know which enum you are using, making your code considerable shorter.
Using Swift Class and Enum from Objective-C
Isn't the enum implicitly Int?
Not really. Objective-C cannot see a Swift enum at all. In Swift, an enum is an object type. Objective-C has no knowledge whatever of any such object type; its only objects are classes. (In Objective-C, enums are just numbers with names.) Therefore, neither a Swift enum type, nor a method that takes or produces a Swift enum, nor a Swift enum property, is exposed to Objective-C
However, in the special case where you say @objc enum BannerStyle: Int
, it is translated into an Objective-C enum for you. So, in Objective-C, names such as BannerStyleDanger
and BannerStyleInfo
will spring to life. But they will just be integers.
enum Values to NSString (iOS)
This is answered here: a few suggestions on implementation
The bottom line is Objective-C
is using a regular, old C
enum
, which is just a glorified set of integers.
Given an enum
like this:
typedef enum { a, b, c } FirstThreeAlpha;
Your method would look like this:
- (NSString*) convertToString:(FirstThreeAlpha) whichAlpha {
NSString *result = nil;
switch(whichAlpha) {
case a:
result = @"a";
break;
case b:
result = @"b";
break;
case c:
result = @"c";
break;
default:
result = @"unknown";
}
return result;
}
Related Topics
How to Find Actual Swiftui API Documentation (And Not Just the Developer Documentation)
Why Should Not Directly Extend Uiview or Uiviewcontroller
Swift: Optional Text in Optional Value
Localizewithformat and Variadic Arguments in Swift
Uiscrollview with Embedded Uiimageview; How to Get the Image to Fill the Screen
How to Load Image in Swift Using Alamofire
Swift - Drawing Text with Drawinrect:Withattributes:
Is There an Alternative to Initialize() in MACos Now That Swift Has Deprecated It
How to Capture Notifications in a Wkwebview
Add Switch in Uitableview Cell in Swift
Optional Field Type Doesn't Conform Protocol in Swift 3
How to Test Whether Generic Variable Is of Type Anyobject
Why Does Swift Playground Shows Wrong Number of Executions
How to Add Kerning to a Textfield in Swiftui
Ondelete Causing Nsrangeexception
Nstextfield, Change Text in Swift