You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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:

  1. 在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>
  1. 创建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)")
        }
    }
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:02:47