Swift 5如何通过路径对Bundle中的plist文件执行解归档操作
解决方案
你遇到的报错本质是unarchivedObject(ofClass:from:)接口不支持直接传入文件路径,需要你先把Bundle里的plist文件读取为Data类型再传入,同时要注意匹配你存储的数组类型,完整的实现逻辑如下:
最简适配代码
guard let fileURL = Bundle.main.url(forResource: MoleName.DNA_ideal_comps.rawValue, withExtension: "plist"), let moleData = try? Data(contentsOf: fileURL), let components = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: moleData) as? [SCNNode], components.count >= 4 else { print("Couldn't find molecule (DNA_ideal_comps)") return } // 后续赋值逻辑和原有代码完全一致 scaleNode_2 = components[0] // DNA A fixedNode_2 = components[1] // 化学键 scaleNode_3 = components[2] // DNA B fixedNode_3 = components[3] // 化学键
注意点
你之前的写法报错还有一个原因:你存储的是[SCNNode]数组类型,属于Swift结构体,无法直接被unarchivedObject(ofClass:from:)识别,需要先解档为Objective-C的NSArray类型,再桥接为Swift数组。
兼容旧归档的鲁棒性写法
如果你的旧归档没有开启安全编码,用上面的最简写法可能会报错,可以用自定义NSKeyedUnarchiver的方式适配:
func unarchiveNodeList(fileName: String) -> [SCNNode]? { // 获取文件URL guard let fileURL = Bundle.main.url(forResource: fileName, withExtension: "plist"), // 读取文件为Data let data = try? Data(contentsOf: fileURL) else { return nil } do { let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) // 旧归档未开安全编码需要设为false,新生成的归档建议开启设为true unarchiver.requiresSecureCoding = false // 解档根对象,指定允许的类集合 guard let nodeArray = unarchiver.decodeObject( of: [NSArray.self, SCNNode.self], forKey: NSKeyedArchiveRootObjectKey ) as? [SCNNode], nodeArray.count >=4 else { unarchiver.finishDecoding() return nil } unarchiver.finishDecoding() return nodeArray } catch { print("文件\(fileName)解档失败:\(error.localizedDescription)") return nil } } // 调用示例 guard let components = unarchiveNodeList(fileName: MoleName.DNA_ideal_comps.rawValue) else { print("Couldn't find molecule (DNA_ideal_comps)") return } // 后续赋值逻辑不变
这种写法的容错性更高,也方便你批量处理90个plist文件,直接传入对应文件名调用即可。
内容的提问来源于stack exchange,提问作者bpedit
相关产品推荐
相关产品推荐

