在 iOS 开发中,进程间通信(IPC)是实现应用间协作和数据共享的关键技术。以下是 iOS 支持的 主要进程间通信机制 及其详细说明:
1. App Groups + UserDefaults/File Sharing #
概述 #
- 核心思想:通过共享容器(Shared Container)或 UserDefaults,在同一开发者账号下的多个应用或扩展(Widget、Watch App 等)之间共享数据。
- 适用场景:主应用与扩展(如 Today Widget)之间的数据同步。
实现步骤 #
启用 App Groups:
- 在 Xcode 中为项目配置
App Groups
Capability,并设置唯一的共享标识符(如group.com.example.app
)。 - 确保主应用和扩展的
Signing & Capabilities
中启用了相同的 App Group。
- 在 Xcode 中为项目配置
共享 UserDefaults:
let sharedDefaults = UserDefaults(suiteName: "group.com.example.app") sharedDefaults?.set("Hello", forKey: "sharedData") sharedDefaults?.synchronize()
共享文件容器:
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.app") let fileURL = containerURL?.appendingPathComponent("sharedFile.txt") try? "Shared Content".write(to: fileURL!, atomically: true, encoding: .utf8)
注意事项 #
- 仅限同一开发者账号下的应用或扩展。
- 共享数据需注意线程安全(如使用
NSFileCoordinator
同步文件访问)。
2. URL Scheme #
概述 #
- 核心思想:通过自定义 URL 协议(如
myapp://
)唤醒其他应用并传递参数。 - 适用场景:简单数据传递(如用户身份令牌、跳转页面路径)。
实现步骤 #
注册 URL Scheme:
在
Info.plist
中添加:<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string>com.example.myapp</string> <key>CFBundleURLSchemes</key> <array> <string>myapp</string> </array> </dict> </array>
处理 URL 请求:
在
AppDelegate
或SceneDelegate
中实现:func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let url = URLContexts.first?.url else { return } if url.scheme == "myapp" { let params = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems // 解析参数并跳转页面 } }
调用其他应用:
if let url = URL(string: "myapp://profile?user=123") { UIApplication.shared.open(url) }
注意事项 #
- URL 参数长度有限,复杂数据需编码(如 Base64)。
- 存在安全风险(需验证来源应用)。
3. XPC Services #
概述 #
- 核心思想:基于
XPC(Cross-Process Communication)
框架实现系统级进程间通信,用于高安全性和稳定性的场景(如应用与系统服务通信)。 - 适用场景:应用扩展(如键盘扩展)、沙盒环境下的权限隔离操作。
实现步骤 #
定义 XPC 服务协议:
@protocol MyXPCProtocol - (void)performTaskWithData:(NSData *)data reply:(void (^)(NSData *response))reply; @end
创建 XPC 服务:
- 在 Xcode 中添加
XPC Service
Target,并实现协议方法。
- 在 Xcode 中添加
主应用连接 XPC 服务:
let connection = NSXPCConnection(serviceName: "com.example.MyXPCService") connection.remoteObjectInterface = NSXPCInterface(with: MyXPCProtocol.self) connection.resume() let service = connection.remoteObjectProxy as? MyXPCProtocol service?.performTaskWithData(data) { response in // 处理响应 }
注意事项 #
- XPC 服务需独立签名和沙盒配置。
- 支持异步通信和错误处理。
4. Darwin Notifications(CFNotificationCenter) #
概述 #
- 核心思想:基于 Darwin 层的跨进程通知机制(
CFNotificationCenter
),通过系统广播发送简单信号。 - 适用场景:系统级事件通知(如锁屏、网络状态变化)。
实现步骤 #
注册通知监听:
CFNotificationCenterAddObserver( CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), { (_, observer, name, _, _) in if let observer = observer, let name = name { let mySelf = Unmanaged<MyClass>.fromOpaque(observer).takeUnretainedValue() mySelf.handleNotification(name: name.rawValue as String) } }, "com.example.notification" as CFString, nil, .deliverImmediately )
发送通知:
CFNotificationCenterPostNotification( CFNotificationCenterGetDarwinNotifyCenter(), CFNotificationName("com.example.notification" as CFString), nil, nil, true )
注意事项 #
- 仅传递通知名称,不携带数据。
- 需要处理线程安全和生命周期管理。
5. Pasteboard(UIPasteboard) #
概述 #
- 核心思想:通过系统剪贴板(
UIPasteboard
)在应用间共享数据(文本、图片、URL 等)。 - 适用场景:用户主动触发的数据共享(如复制粘贴)。
实现步骤 #
// 写入数据
let pasteboard = UIPasteboard.general
pasteboard.string = "Copied Text"
// 读取数据
if let text = UIPasteboard.general.string {
print("剪贴板内容:\(text)")
}
注意事项 #
- 剪贴板数据对所有应用可见(敏感信息需加密)。
- iOS 14+ 限制后台读取剪贴板。
6. Keychain Sharing #
概述 #
- 核心思想:通过共享钥匙串(Keychain)在应用间安全存储和访问敏感信息(如密码、令牌)。
- 适用场景:跨应用共享用户凭证。
实现步骤 #
启用 Keychain Sharing:
- 在 Xcode 中配置
Keychain Sharing
Capability,并设置相同的 Keychain Group(如com.example.keychaingroup
)。
- 在 Xcode 中配置
读写 Keychain:
let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: "userToken", kSecAttrService as String: "com.example.service", kSecAttrAccessGroup as String: "com.example.keychaingroup", kSecValueData as String: "secretToken".data(using: .utf8)! ] SecItemAdd(query as CFDictionary, nil)
注意事项 #
- 需相同开发者账号和配置。
- 数据加密存储,安全性高。
7. Socket 通信(Network/Berkeley Sockets) #
概述 #
- 核心思想:通过 TCP/UDP 套接字实现跨设备或本机进程间通信。
- 适用场景:需要高吞吐量的数据传输(如本地服务器与客户端通信)。
实现步骤 #
// 服务端
let serverSocket = socket(AF_INET, SOCK_STREAM, 0)
var serverAddr = sockaddr_in()
serverAddr.sin_port = UInt16(8080).bigEndian
bind(serverSocket, &serverAddr, socklen_t(MemoryLayout<sockaddr_in>.size))
listen(serverSocket, 5)
// 客户端
let clientSocket = socket(AF_INET, SOCK_STREAM, 0)
connect(clientSocket, &serverAddr, socklen_t(MemoryLayout<sockaddr_in>.size))
注意事项 #
- iOS 应用需声明网络权限(
NSLocalNetworkUsageDescription
)。 - 本机通信可使用
localhost
或127.0.0.1
。
总结对比表 #
机制 | 适用场景 | 数据安全 | 复杂度 | 限制条件 |
---|---|---|---|---|
App Groups | 主应用与扩展间共享数据 | 中 | 低 | 需同一开发者账号 |
URL Scheme | 简单参数传递与跳转 | 低 | 低 | 参数长度受限 |
XPC Services | 系统级服务与沙盒环境通信 | 高 | 高 | 需配置 XPC 目标 |
Darwin Notifications | 跨进程发送简单信号 | 低 | 中 | 不携带数据 |
Pasteboard | 用户主动触发的数据共享 | 低 | 低 | 数据对所有应用可见 |
Keychain Sharing | 安全共享敏感信息 | 高 | 中 | 需配置 Keychain Group |
Socket 通信 | 高吞吐量数据传输(本机或网络) | 可定制 | 高 | 需网络权限 |
选择建议 #
- 简单数据共享:优先使用
App Groups
或Pasteboard
。 - 安全敏感数据:使用
Keychain Sharing
。 - 系统级通信:选择
XPC Services
或Darwin Notifications
。 - 用户主动跳转:通过
URL Scheme
实现。
通过合理选择 IPC 机制,可以实现高效、安全的 iOS 应用间协作。