Refining Objective-C APIs for Swift with NS_SWIFT_NAME

NS_SWIFT_NAME gives Objective-C code a Swifty alias without changing the original API. Use it to modernize legacy frameworks by removing prefixes for Swift consumption.
WHY IT EXISTS: Objective-C and Swift have different naming conventions. Objective-C favors long, descriptive names with prefixes (like NS or a custom prefix) to avoid collisions. Swift uses modules for namespacing, making these prefixes redundant. NS_SWIFT_NAME was created to bridge this gap, allowing old APIs to feel new in Swift without breaking existing Objective-C code.
THE MENTAL MODEL: Think of NS_SWIFT_NAME as a "stage name" for your Objective-C code when it performs in a Swift environment. The code has its legal, birth name (the Objective-C name) that it uses backstage and in all official Objective-C documents. But when it's on the Swift stage, it uses its slicker, more modern stage name.
HOW IT WORKS: You add the NS_SWIFT_NAME macro to your Objective-C header (.h) file, right after the declaration of a class, enum, protocol, or function. You provide the desired Swift name as an argument to the macro. For example, typedef NS_ENUM(NSInteger, TSKTaskState) { ... } NS_SWIFT_NAME(Task.State);. When the Swift compiler imports this header, it replaces all occurrences of TSKTaskState with Task.State.
WHEN TO USE IT: This is a key tool for incremental migration from Objective-C to Swift. Use it to remove class prefixes (e.g., ACMEWidget becomes Widget), create more ergonomic method signatures, and nest related types like enums inside a class for better namespacing in Swift (as seen in the Task.State example).
WHEN NOT TO USE IT: Don't use this for new, Swift-first codebases. If you don't need to maintain Objective-C compatibility, just write idiomatic Swift from the start. Also, avoid creating drastically different names that hide the connection to the original API; the goal is refinement, not complete obfuscation, which can make debugging harder.
ONE CANONICAL EXAMPLE: To rename an Objective-C class, you'd write this in the header: @interface MYAppController : NSObject @end NS_SWIFT_NAME(AppController). In your Swift code, you can now instantiate it using let controller = AppController(). However, in any .m file, you must still use MYAppController *controller = [[MYAppController alloc] init];.
Read the original → developer.apple.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.