UIDocumentPickerDelegate的didPickDocumentsAt方法在真机非Debug模式下不触发,模拟器及真机Debug模式正常
嗨,这种只在Release模式下掉链子的问题确实挺头疼的,我之前踩过类似的坑,咱们从几个最可能的方向排查:
先排查编译优化导致的方法被“吃掉”
Release模式默认会开启Fastest, Smallest [-Os]级别的编译优化,有时候会把签名“不够标准”的delegate方法优化掉。你可以先临时把Release的Optimization Level改成None [-O0](在Build Settings里搜Optimization Level)测试一下,如果改成后正常了,那就是优化的问题。这时候要仔细核对你的delegate方法签名,必须和系统定义的完全一致,比如Swift里的正确签名是:func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { // 你的处理逻辑 }注意下划线、参数类型、方法名一个都不能错,哪怕少个下划线,Release模式下编译器可能直接忽略这个方法,不会触发。
检查delegate的内存管理问题
Release模式下ARC的内存回收策略更激进,很可能你的UIDocumentPickerViewController实例或者持有delegate的对象被提前释放了。比如如果你是在按钮点击事件里直接创建局部的picker:@IBAction func pickButtonTapped(_ sender: UIButton) { let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.item]) picker.delegate = self present(picker, animated: true) }这种情况下,Release模式下ARC可能会在picker弹出后就把这个局部实例回收掉,导致delegate失效。解决办法是把picker声明为视图控制器的属性,延长它的生命周期:
private var documentPicker: UIDocumentPickerViewController? @IBAction func pickButtonTapped(_ sender: UIButton) { let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.item]) picker.delegate = self documentPicker = picker present(picker, animated: true) }然后在
didPickDocumentsAt和documentPickerWasCancelled方法里,记得把documentPicker = nil释放掉。别被日志输出骗了
Release模式下默认会关闭print语句的输出,你加的调试print可能根本没显示,不代表方法没触发。换成NSLog或者写入本地文件来验证,比如:func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { NSLog("文档选择完成,URL列表:%@", urls as NSArray) // 你的处理逻辑 documentPicker = nil }然后通过Xcode的「Window - Devices and Simulators」选中你的设备,打开控制台就能看到NSLog的输出,这样才能确认方法到底有没有被调用。
检查Info.plist和能力配置
虽然Debug模式下正常,但还是要确认Release模式的target有没有开启对应的能力,比如如果是访问iCloud文件,要确保iCloud能力是开启的,容器ID配置正确;另外Info.plist里有没有添加必要的权限描述,比如如果涉及到特定类型的文件,有没有对应的声明(不过这个一般Debug和Release是共用的,还是核对下更放心)。
内容来源于stack exchange

