iOS同应用跨设备传递嵌套数组[[String]]的最优方案咨询
嘿,针对你要在两部iPhone的同一APP间传递嵌套数组的需求,我来帮你梳理下最优方案,先把你提到的两个组件的区别讲清楚,再一步步说实现步骤:
这俩组件的定位完全不同,适配的场景也不一样:
- UIActivityViewController:这是系统提供的快速调用原生分享能力的组件,能直接在你的主APP内触发AirDrop、短信、邮件等分享通道,不需要额外创建扩展Target。它是「主动发起分享」的最佳选择,完美匹配你想要的“点击分享→发送→对方唤起APP加载”流程。
- Share Extension:这是一个独立的扩展模块,作用是让其他APP能把内容分享到你的APP(比如用户在Safari里分享网页到你的APP)。它只能被动接收外部内容,没法主动发起分享,所以对你的需求来说,它不是发起端的解决方案,除非你还需要支持从其他APP导入数据。
适配你需求的最优方案:UIActivityViewController + AirDrop + 自定义UTI
这套方案完全贴合你的理想流程,而且实现起来简单高效,不需要自己造蓝牙传输的轮子(AirDrop本身就是基于蓝牙+WiFi的高效近场传输方案)。
第一步:把嵌套数组转成可传输的格式
嵌套数组[[String]]没法直接通过AirDrop传递,我们可以把它转成JSON格式——JSON能完美保留嵌套结构,序列化和解析都很方便。
示例代码:
let targetArray = [["John", "27", "First", "Castle"],["Tom", "25", "Second", "Boat"]] // 转成JSON Data do { let jsonData = try JSONSerialization.data(withJSONObject: targetArray, options: .prettyPrinted) // 后续用这个jsonData作为分享内容 } catch { print("JSON转换失败:\(error.localizedDescription)") }
第二步:用UIActivityViewController发起AirDrop分享
为了让对方接收后能直接唤起你的APP,我们需要先给APP定义一个自定义UTI(统一类型标识符),告诉系统“这个数据属于我的APP”。
先配置自定义UTI
在Info.plist里添加配置:
- 右键选择「Add Row」,找到
Exported Type Identifiers,添加一个子项 - 子项的
Type Identifier设为自定义值(比如com.yourapp.customarray) Type Description填你的数据描述(比如“用户信息嵌套数组”)Conforms To选择public.json(因为我们用JSON格式传输)
发起分享的代码
// 假设已经拿到转换好的jsonData let activityVC = UIActivityViewController(activityItems: [jsonData], applicationActivities: nil) // 可选:过滤掉不需要的分享选项,只保留AirDrop activityVC.excludedActivityTypes = [.message, .mail, .print, .copyToPasteboard] // iPad上需要设置popover的展示位置 if let popoverController = activityVC.popoverPresentationController { popoverController.sourceView = yourShareButton popoverController.sourceRect = yourShareButton.bounds } present(activityVC, animated: true)
第三步:接收端APP处理传入的数据
当对方通过AirDrop接收数据并选择用你的APP打开时,系统会把数据传递到你的APP,你需要在APP的生命周期方法里解析数据。
针对iOS 13+的SceneDelegate场景
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let fileURL = URLContexts.first?.url, fileURL.isFileURL else { return } do { let data = try Data(contentsOf: fileURL) // 解析回嵌套数组 if let receivedArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String]] { // 这里拿到了传递过来的数组,做后续加载逻辑 print("接收成功:\(receivedArray)") // 比如通知主界面更新数据 NotificationCenter.default.post(name: NSNotification.Name("ReceivedUserArray"), object: receivedArray) } } catch { print("解析失败:\(error.localizedDescription)") } }
针对iOS 12及以下的AppDelegate场景
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { guard url.isFileURL else { return false } do { let data = try Data(contentsOf: url) if let receivedArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String]] { // 处理数据逻辑 } } catch { print("解析失败:\(error.localizedDescription)") } return true }
额外配置:让APP能识别自定义UTI的文件
在Info.plist里添加Document Types配置:
- 添加一个子项,
CFBundleTypeName填数据名称(比如“用户数组数据”) LSHandlerRank设为OwnerLSItemContentTypes里添加你之前定义的自定义UTI(com.yourapp.customarray)
为什么这是最优方案?
- 高效省心:直接复用系统AirDrop的传输能力,不需要自己实现蓝牙配对、数据传输的复杂逻辑,系统已经帮你处理了所有底层细节。
- 体验流畅:完全符合你想要的“点击分享→AirDrop发送→唤起APP加载”的无缝流程,用户不需要额外操作。
- 兼容性强:UIActivityViewController支持iOS 7+,AirDrop支持iOS 7+的设备,不需要额外权限申请(系统会自动处理蓝牙、WiFi权限)。
内容的提问来源于stack exchange,提问作者user13891746
相关产品推荐
相关产品推荐

