iOS14运行正常iOS15下NSURL URLByAppendingPathExtension崩溃如何解决
问题解答
1. 报错中「components」的含义
报错里提到的components是指URL路径的组成片段,比如URL file:///用户/文档/笔记/note 里的用户、文档、笔记、note都属于路径组件。你遇到的错误本质是iOS15对UIDocument的内部实现做了修改:保存文件时系统会自动尝试给路径追加默认后缀,调用URLByAppendingPathExtension方法时传入了空值,才触发崩溃。
你代码中NoteFile初始化生成的fileURL本身是没有后缀的:
let url = NEFileManager.noteFromAssetFolder(id: noteId)?.appendingPathComponent(name) // name固定为"note",无后缀 super.init(fileURL: url!)
iOS14及更早版本的UIDocument保存无后缀文件时不会自动补后缀,iOS15+新增的自动补后缀逻辑会校验文件UTI对应的后缀,如果没有合法的后缀值就会传空触发崩溃。
2. 修复方案
方案1:给note文件加固定后缀
直接修改NoteFile的文件名定义,给文件名加固定后缀(比如.note、.txt都可以),从根源避免系统自动补后缀的逻辑触发:
// 修改NoteFile内的name定义 private let name = "note.note" // 追加自定义后缀即可
方案2:给NoteFile指定合法UTType
如果不想改动现有存量文件的命名,就重写UIDocument的文件类型属性,声明对应的文件格式标识:
首先导入UniformTypeIdentifiers框架,再给NoteFile新增如下实现:
import UniformTypeIdentifiers extension NoteFile { override class var readableTypes: [String] { [UTType.plainText.identifier] // 也可以用你自定义的UTI标识 } override class var writableTypes: [String] { [UTType.plainText.identifier] } }
方案3:补充空值校验兜底
你现有代码中大量使用强制解包(!),比如url!、fileWrappers!,本身就存在不稳定风险,建议全部替换为可选绑定校验:
// 修改NoteFile初始化方法,避免强制解包崩溃 convenience init?(noteDescriptor: NoteDescriptor) { let noteId = noteDescriptor.id guard let baseUrl = NEFileManager.noteFromAssetFolder(id: noteId) else { return nil } let url = baseUrl.appendingPathComponent("note") self.init(fileURL: url) self.noteId = noteId } // 保存前先校验noteFile是否存在 func saveToNoteFile(completion: ((Bool) -> Void)?) { guard let noteFile = noteFile else { completion?(false) return } // 原有保存逻辑不变 }
内容的提问来源于stack exchange,提问作者user2312844
相关产品推荐
相关产品推荐

