如何在iOS应用中接收Mac通过AirDrop发送的文本文件?
iOS 16应用接收AirDrop文本文件的解决方案
问题描述
我希望在iPhone端的iOS应用中接收Mac(macOS 13.4)通过AirDrop发送的文本文件,当前使用Swift 5.8、Xcode 14.3开发iOS 16应用。
已在Info.plist中添加如下配置:
<key>UIFileSharingEnabled</key><true/> <key>CFBundleDocumentTypes</key><array><dict> <key>CFBundleTypeName</key><string>AirDrop Text File Type</string> <key>LSHandlerRank</key> <string>Default</string> <key>LSItemContentTypes</key><array> <string>public.text</string> </array> </dict> </array>在iPhone的AirDrop菜单中可以看到我的TestApp,但无法获取到接收的url或数据,编写的代码如下,
application(_:open:options:)方法没有触发:@main struct TestApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { var body: some View { Text("testing") } } class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { print("\ndidFinishLaunchingWithOptions\n") // 能打印 return true } func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { print("\nurl: \(url)\n") // 无法打印 return true } }请问如何获取文件内容或其URL以进行读取?
核心原因
iOS 13+采用Scene生命周期,原UIApplicationDelegate中的application(_:open:options:)方法不再触发,需使用Scene相关回调处理文件接收。
解决方案
方法一:SwiftUI原生实现(推荐)
无需依赖AppDelegate,直接在Scene中使用onOpenURL修饰符处理:
@main struct TestApp: App { var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in // 接收AirDrop传入的文件URL print("接收文件URL: \(url)") // 读取文件内容示例 do { let fileContent = try String(contentsOf: url) print("文件内容: \(fileContent)") // 如需长期保存,可调用下方的保存方法 saveFileToDocuments(from: url) } catch { print("读取文件失败: \(error.localizedDescription)") } } } } // 将临时文件保存到Documents目录(可选) private func saveFileToDocuments(from tempURL: URL) { guard let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } let destURL = docsDir.appendingPathComponent(tempURL.lastPathComponent) do { if FileManager.default.fileExists(atPath: destURL.path) { try FileManager.default.removeItem(at: destURL) } try FileManager.default.copyItem(at: tempURL, to: destURL) print("文件已保存至: \(destURL)") } catch { print("保存文件失败: \(error.localizedDescription)") } } } struct ContentView: View { var body: some View { Text("testing") } }
方法二:使用SceneDelegate(兼容传统架构)
若需保留AppDelegate,需额外实现UISceneDelegate:
- 在Info.plist中添加Scene配置(如无):
<key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <false/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict> <key>UISceneConfigurationName</key> <string>Default Configuration</string> <key>UISceneDelegateClassName</key> <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> <key>UISceneStoryboardFile</key> <string>Main</string> </dict> </array> </dict> </dict>
- 创建SceneDelegate类:
class SceneDelegate: NSObject, UIWindowSceneDelegate { func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let fileURL = URLContexts.first?.url else { return } print("接收文件URL: \(fileURL)") // 读取文件内容 do { let content = try String(contentsOf: fileURL) print("文件内容: \(content)") } catch { print("读取失败: \(error.localizedDescription)") } } }
- 修改AppDelegate,移除无效的
application(_:open:options:)方法:
class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { print("\ndidFinishLaunchingWithOptions\n") return true } }
注意事项
- AirDrop传入的文件默认存放在应用临时目录,重启应用后会被系统清理,如需长期保存需手动复制到Documents目录。
- 你已配置的
LSHandlerRank和LSItemContentTypes正确,确保了应用能被AirDrop识别为文本文件接收方。
内容的提问来源于stack exchange,提问作者sumida
相关产品推荐
相关产品推荐

