Migrating Objective‑C to Swift: Benefits, Practices, and a Practical Guide
With Swift 5’s stable ABI shrinking app bundles, developers can migrate Objective‑C code top‑down—starting at UI layers—to leverage Swift’s safety‑focused optionals, value‑type structs, powerful enums, functional and protocol‑oriented paradigms, while handling interoperability via @objc and dynamic, ultimately future‑proofing apps for SwiftUI, cross‑platform frameworks, and continued iOS/macOS relevance.
With the release of Swift 5.0 the language ABI has become stable, eliminating the major pain point that discouraged many developers from adopting Swift. The stable ABI also allows the Swift runtime to be bundled with the OS, reducing app size because Swift no longer needs to be shipped inside the application package.
Why migrate to Swift? Beyond ABI stability, Swift offers safety features such as optionals, value‑type structs, and keywords like guard and defer . These language constructs make it easier to write crash‑free, readable code.
Programming paradigm enrichment includes first‑class functional programming, protocol‑oriented programming with default implementations, and powerful generics that enable more reusable and flexible code.
Migration strategy – start from the top of the UI layer (View Controllers and Views) and work downwards. This top‑down approach limits the amount of bridging code needed and isolates changes, making testing and stability easier.
Typical iOS project structure is shown below (UI layer at the top, lower‑level modules underneath). Migrating UI‑related classes first allows Swift code to call existing Objective‑C modules without additional adapters.
Using Swift value types – structs are copied on assignment (Copy‑on‑Write) and provide safety and performance benefits. Example:
var a = 1
var b = a
b = 2Converting an Objective‑C model to a Swift struct :
struct Video {
let videoId: String
let videoTitle: String
let videoSubtitle: String
}Enums in Swift can replace Objective‑C NS_ENUM and carry associated values and methods:
enum Trade {
case VIP(userId: String)
case singleVideo(videoID: String)
func buy() {
switch self {
case .VIP(let userId):
// buy vip with userId
case .singleVideo(let videoId):
// buy single video with videoId
}
}
}Usage:
Trade.VIP(userId: "349951").buy()Interoperability challenges – Swift classes must inherit from NSObject and be marked @objc to be callable from Objective‑C. Example of bridging a method:
// Objective‑C
- (void)someMethod {
A *a = [A new];
[a doWork];
}
// Swift
class A: NSObject {
@objc func doWork() {
// do something
}
}Note that @objc only exposes the method; for true dynamic dispatch you need the dynamic keyword.
Missing Swift equivalents – features like @synchronized can be reimplemented using objc_sync_enter/exit wrapped in a Swift function:
func synchronized(_ lock: AnyObject, block: () -> Void) {
objc_sync_enter(lock)
block()
objc_sync_exit(lock)
}Singletons in Objective‑C use dispatch_once ; in Swift a static constant suffices:
static let shared = YourObject()When dispatch_once is still needed, a custom extension on DispatchQueue can provide a similar one‑time execution:
public extension DispatchQueue {
private static var _onceTokens = [String]()
public class func once(token: String, block: () -> Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTokens.contains(token) { return }
_onceTokens.append(token)
block()
}
}Finally, the article looks ahead: SwiftUI enables a single UI codebase for macOS and iOS, Swift runs on Linux, and cross‑platform UI frameworks (e.g., SCADE) allow sharing code between Android and iOS. Despite the rise of Flutter, Swift remains essential for core iOS/macOS business logic and is increasingly the primary language recommended by Apple.
Youku Technology
Discover top-tier entertainment technology here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.