Integrating Swift into an Existing iOS Client: Preparation, Framework Design, and Common Issues
This article outlines the preparation, framework redesign, and common challenges of integrating Swift into an existing Objective‑C iOS client, covering ABI stability, mixed compilation, module configuration, code standards, and future migration plans.
Background
Swift, Apple’s first‑class language, achieved ABI stability in March 2019, meaning binaries compiled with Swift 5 or later can run on any Swift 5.0+ runtime, reducing app size and memory usage because the system provides the Swift runtime.
For Haodafu’s medical platform, adopting Swift presents a valuable opportunity, and this article explains the required preparations, basic framework design, and solutions to common Swift development issues.
Preparation for Swift Integration
Haodafu’s iOS client code dates back to 2011 and is primarily written in Objective‑C. The team first conducted a technical survey to determine the appropriate Swift version and evaluated third‑party Swift libraries, noting that the global Swift community is more active than the domestic one.
Research showed Swift offers superior development efficiency and performance, and Apple’s documentation now prioritises Swift, making migration urgent as Apple pushes Swift and SwiftUI across its platforms.
Basic Framework Design
The client uses a component‑based architecture with CocoaPods for dependency management. After Swift adoption, private libraries were selectively refactored into Swift, creating a set of Swift‑compatible base libraries while keeping unchanged components that do not require immediate migration.
For UI controls, networking, image handling, and payment libraries, refactoring impacts testing and iteration time; therefore, only essential components were updated, and new components are written in Swift by default.
After a year of gradual migration, the client now has fully Swift‑implemented features such as live streaming and message boards, with other major features using a mixed Swift/Objective‑C approach.
Problems Encountered in Swift Migration
Traditional Objective‑C projects face recurring issues such as mixed compilation, module system configuration, and code style enforcement.
How to mix Swift and Objective‑C in the main app or modular components
Module system setup
Ensuring Swift code conforms to style guidelines
…
1. Swift and Objective‑C Mixed Compilation
When adding the first Swift file to an Objective‑C target, Xcode prompts to create a bridging header; simply click “Create”.
In a Swift file, import an Objective‑C class using #import in the bridging header. Conversely, an Objective‑C file can import Swift symbols with import "ProductModuleName-Swift.h" , where ProductModuleName is the target name.
For modular components, configure CocoaPods by adding s.pod_target_xcconfig = {'DEFINES_MODULE' => 'YES'} , generate an umbrella.h (or create one) that includes the Objective‑C headers to be exposed, and then import the module in Swift with import Module .
2. Module System
2.1 LLVM Module System
Apple introduced the LLVM module system in 2012, replacing traditional #include directives with import statements (e.g., import std.io ), which provides a complete semantic description, improves compile‑time scalability, reduces fragmentation, and offers better tooling support.
Provides a full semantic description of a framework
Improves compile‑time scalability by avoiding repeated header parsing
Reduces fragmentation; each module is processed once
Tool‑friendly; compilers can obtain richer module metadata
…
2.2 modulemap File
The modulemap file describes the structure of a framework or library; the default filename is module.modulemap . Using the umbrella header keyword, all .h files in HDFIMComponent-umbrella.h are imported.
The umbrella header acts as a master header file; for example:
#import <UIKit/UIKit.h>
#import <UIKit/UIViewController.h>
#import <UIKit/UILabel.h>
#import <UIKit/UIButton.h>
#import <UIKit/UIDatePicker.h>2.3 Swift Module
Each target (framework or app) is a Swift module. Importing a module with import brings its namespace and public/open symbols into scope, providing an independent access‑control domain.
A namespace matching the module name
An independent access‑control scope
This explains why classes defined in different Swift files can be used without explicit include statements.
3. Swift Code Standards
To ensure consistent style, Haodafu introduced SwiftLint, an open‑source linter from Realm, integrated with SonarQube for reporting. SwiftLint scans the codebase, enforces formatting rules, and helps keep “code smell” count at zero.
Future Plans
Swift’s popularity is rising, and Apple’s push makes it essential for future iOS development. Haodafu plans to upgrade Swift versions annually, adopt Swift Package Manager to replace CocoaPods, and move towards declarative UI.
Future articles will dive deeper into Swift Package Manager integration, Swift‑Objective‑C interop pitfalls, and SwiftLint integration with SonarQube.
Author
Tao Qingwei – iOS engineer at Haodafu, responsible for component architecture, core libraries, client stability, and Swift adoption.
References
August Headline: Holiday season in the programming language world
Swift ABI Stability
Apple Importing Objective‑C into Swift
CocoaPods umbrella.h
Swift programming language
SwiftLint
Access Control
HaoDF Tech Team
HaoDF Online tech practice and sharing—join us to discuss and help create quality healthcare through technology.
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.