iOS中通过openURL跨应用启动时如何传递任意多个对象?
iOS跨App传递多对象(MyApp1→MyApp2)方案
我来帮你搞定从MyApp1用openURL启动MyApp2并传递任意多对象的需求~你说的用Dictionary包裹对象的思路完全可行,核心是把Dictionary转成URL能承载的格式,下面是具体实现步骤:
1. 给MyApp2配置URL Scheme
首先得让MyApp2能被其他App通过URL唤起,步骤如下:
- 打开MyApp2的
Info.plist,添加CFBundleURLTypes数组 - 在数组里新增一个字典,设置
CFBundleURLSchemes为你自定义的Scheme(比如myapp2),CFBundleURLName可以填App的标识(比如com.yourcompany.MyApp2)
或者在Xcode的Target设置里,选择Info→URL Types,点击+号添加,直接填写Scheme名称更直观。
2. 序列化包含任意对象的Dictionary
因为URL只能传递字符串,所以我们需要把Dictionary(里面包含自定义对象)转成URL安全的字符串:
- 首先确保你的自定义对象遵循
Codable协议(或者NSCoding,不过Codable更简洁) - 把Dictionary转成JSON Data,再转成Base64字符串(避免URL编码的麻烦),或者直接对JSON字符串做URL编码
示例代码(MyApp1中):
// 自定义对象示例 struct CustomObject: Codable { let id: Int let name: String } // 构造包含多对象的Dictionary let obj1 = CustomObject(id: 1, name: "Obj1") let obj2 = CustomObject(id: 2, name: "Obj2") let dataDict: [String: Any] = [ "userID": 123, "customObjs": [obj1, obj2], "message": "Hello from MyApp1" ] // 序列化Dictionary do { // 先把Dictionary转成JSON Data let jsonData = try JSONSerialization.data(withJSONObject: dataDict, options: []) // 转成Base64字符串(URL安全) let base64String = jsonData.base64EncodedString() // 或者直接转成JSON字符串再做URL编码 // let jsonString = String(data: jsonData, encoding: .utf8)! // let encodedString = jsonString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! } catch { print("序列化失败:\(error)") }
3. 构造URL并唤起MyApp2
把序列化后的字符串作为URL的参数,构造完整的Scheme URL,然后调用open方法:
// 构造URL guard let url = URL(string: "myapp2://open?data=\(base64String)") else { print("URL构造失败") return } // 唤起MyApp2 if UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } else { print("MyApp2未安装或未配置Scheme") }
4. MyApp2接收并解析数据
在MyApp2中,需要在合适的生命周期方法里接收URL并解析:
如果你用的是UIKit(AppDelegate):
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { // 取出参数 guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let dataParam = components.queryItems?.first(where: { $0.name == "data" })?.value else { return false } // 解析Base64字符串 guard let jsonData = Data(base64Encoded: dataParam), let dataDict = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] else { return false } // 从Dictionary中取出对象,比如解析自定义对象数组 if let customObjsData = try? JSONSerialization.data(withJSONObject: dataDict["customObjs"] as? [[String: Any]] ?? []), let customObjs = try? JSONDecoder().decode([CustomObject].self, from: customObjsData) { print("收到自定义对象:\(customObjs)") } // 处理其他数据 let userID = dataDict["userID"] as? Int let message = dataDict["message"] as? String return true }
如果你用的是SceneDelegate:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let url = URLContexts.first?.url else { return } // 后续解析逻辑和上面AppDelegate的一致 }
备选方案:处理大对象传递
如果你的对象体积很大,URL的长度可能会受限(iOS里URL一般建议不超过2048字符),这时候可以用App Groups共享数据:
- 给两个App配置同一个App Group
- MyApp1把大对象存在UserDefaults(App Group容器)或者FileManager的共享目录里,生成一个唯一标识
- 把这个标识通过URL传递给MyApp2,MyApp2再根据标识去共享容器里取数据
这样就不用担心URL长度限制的问题啦~
内容的提问来源于stack exchange,提问作者M.Masa
相关产品推荐
相关产品推荐

