Objective-C Macro Keywords

NS_SWIFT_NAME

Renaming OC API names for Swift

Renaming enums cases

Normally, the compiler will clip the enum’s prefix when importing them to Swift. But there are some exceptions.

1
2
3
4
5
6
7
8
9
10
11
12
13
// Objective-C Interface
typedef NS_ENUM(NSInteger, DisplayMode) {
DisplayMode256Color,
DisplayModeThousandsOfColors,
DisplayModeMillionsOfColors
};

// Generated Swift Interface
enum DisplayMode : Int {
case mode256Colors = 0
case modeThousandsOfColors = 1
case modeMillionsOfColors = 2
}

The DisplayMode256Color would starts with numbers if the compiler removes its prefix. So the compiler would retain the model as beginning.
We can use NS_SWIFT_NAME to modify the case’s name in Swift to avoid this trouble.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Objective-C Interface
typedef NS_ENUM(NSInteger, DisplayMode) {
DisplayMode256Colors NS_SWIFT_NAME(with256Colors),
DisplayModeThousandsOfColors,
DisplayModeMillionsOfColors,
};

// Generated Swift Interface
enum DisplayMode : Int {
case with256Colors = 0
case thousandsOfColors = 1
case millionsOfColors = 2
}

Converting factory methods in OC to convenience initialization methods in Swift

Sometimes, the factory methods we written in OC don’t conform the compiler’s conversion standard. We can convert them to initialization methods in Swift manually.

1
2
3
4
5
6
7
8
9
// Objective-C Interface
@interface MyController : UIViewController
+ (instancetype)standardControllerForURLKind:(URLKind)kind NS_SWIFT_NAME(init(URLKind:));
@end

// Generated Swift Interface
class MyController: UIViewController {
convenience init(URLKind kind: URLKind)
}

The compiler can only recognize the controllerForURLKind as a factory method. The class MyController’s suffix must equal to the factory method’s prefix.

Renaming classes and properties to nested types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Objective-C Interface
NS_SWIFT_NAME(Sandwich.Preferences) // Renaming classes name.
@interface SandwichPreferences : NSObject
@property BOOL includesCrust NS_SWIFT_NAME(isCrusty); // Renaming properties.
@end

@interface Sandwich : NSObject
@end

// Generated Swift Interface
extension Sandwich {
open class Preferences : NSObject {
open var isCrusty: Bool
}
}

open class Sandwich : NSObject {
}

// Use it in Swift
var preferences = Sandwich.Preferences()
preferences.isCrusty = true

Renaming enums to nested types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Declare in Objective-C
typedef NS_ENUM(NSInteger, SandwichBreadType) {
brioche, pumpernickel, pretzel, focaccia
} NS_SWIFT_NAME(SandwichPreferences.BreadType); // The class's name must be OC name.

// Generated Swift Interface
extension Sandwich.Preferences {
public enum BreadType : Int {
case brioche = 0
case pumpernickel = 1
case pretzel = 2
case focaccia = 3
}
}

// Use it in Swift
let type = Sandwich.Preferences.BreadType.focaccia

Renaming Objective-C methods

1
2
3
4
5
// Declare in Objective-C
- (NSSet<NSString *> *)previousMissionsFlownByAstronaut:(SKAstronaut *)astronaut NS_SWIFT_NAME(previousMissions(flownBy:));

// Generated Swift Interface
open func previousMissions(flownBy astronaut: SKAstronaut) -> Set<String>

Renaming Objective-C enums and global functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Declare in Objective-C
typedef NS_ENUM(NSInteger, SKFuelKind) {
SKFuelKindH2 = 0,
SKFuelKindCH4 = 1,
SKFuelKindC12H26 = 2
} NS_SWIFT_NAME(SKFuel.Kind);

NSString *SKFuelKindToString(SKFuelKind) NS_SWIFT_NAME(string(from:));

// Generated Swift Interface
extension SKFuel {
public enum Kind : Int {
case H2 = 0
case CH4 = 1
case C12H26 = 2
}
}

public func string(from _: SKFuel.Kind) -> String

Converting global functions

  • Convert to static methods
    The dot . means its a static method.
1
2
3
4
5
6
7
// Declare in Objective-C
NSString *SKFuelKindToString(SKFuelKind) NS_SWIFT_NAME(SKFuelKind.string(from:));

// Generated Swift Interface
extension SKFuel.Kind {
public static func string(from _: SKFuel.Kind) -> String
}
  • Convert to instance methods
    Modifying the parameter’s label to self can convert the method to a instance function.
1
2
3
4
5
6
7
// Declare in Objective-C
NSString *SKFuelKindToString(SKFuelKind) NS_SWIFT_NAME(SKFuelKind.string(self:));

// Generated Swift Interface
extension SKFuel.Kind {
public func string() -> String
}
  • Convert to instance properties
    Prefixing getter: or setter: for the declaration can convert the method to a property
1
2
3
4
5
6
7
// Declare in Objective-C
NSString *SKFuelKindToString(SKFuelKind) NS_SWIFT_NAME(getter:SKFuelKind.description(self:));

// Generated Swift Interface
extension SKFuel.Kind {
public var description: String { get }
}

@objc

Renaming Swift methods for Objective-C

1
@objc(previousMissionsFlownByAstronaut:) func previousMissions(flownBy astronaut: SKAstronaut) -> Set<String> { ... }