使用Bundle解码本地JSON文件时Xcode预览进程崩溃无编译错误如何解决?
问题原因&解决方案
- 类型不匹配:JSON中
DOUBAN_SCORE、DOUBAN_VOTES、MINS三个字段的实际值是字符串类型(带双引号),但你的Movie1模型里对应定义的是Double?、Int?、Double?数值类型,JSONDecoder无法自动将字符串转成数值,直接解码失败。 - 根数据结构不匹配:你给出的JSON示例根节点是单个
Movie1对象,但是解码时你指定了目标类型为[Movie1]数组,结构对不上也会导致解码失败。 - 不可见字符干扰:JSON的第一个键
MOVIE_ID前面存在一个零宽空格不可见字符,会导致和模型里的MOVIE_ID键匹配失败,无法解析对应字段。 - 强制错误处理风险:你的Bundle扩展里用
try?忽略了所有具体错误,一旦解码失败直接触发fatalError,会直接导致进程崩溃;同时Xcode Canvas预览的沙箱路径和常规运行环境不同,预览时有可能无法读取到JSON文件,直接触发崩溃。 - 数组越界风险:你直接通过
datas[1]取值,若数组长度不足2会触发数组越界崩溃。
修复步骤
1. 修正JSON数据
- 去掉
MOVIE_ID前面的不可见字符,保证键名和模型完全一致 - 去掉三个数值字段的双引号,改成纯数值:
"DOUBAN_SCORE":8.2、"DOUBAN_VOTES":187、"MINS":0 - 如果需要解析成数组,给整个JSON外层套上中括号
[],变成数组结构
2. 优化Bundle扩展的错误处理,方便排查问题
import Foundation extension Bundle{ func decode<T:Codable>(filename:String) throws -> T { guard let url = self.url(forResource: filename, withExtension: nil) else { throw NSError(domain: "BundleDecode", code: -1, userInfo: [NSLocalizedDescriptionKey: "找不到文件\(filename)"]) } let data = try Data(contentsOf: url) return try JSONDecoder().decode(T.self, from: data) } }
3. 调整视图代码,避免预览崩溃
struct homePage: View { // 用State延迟加载,避免初始化时直接解码失败 @State private var datas: [Movie1] = [] var body: some View { HStack { Text("hello") // 先判断数组长度再取值,避免越界 if datas.count > 1 { Text(datas[1].ACTORS ?? "none") } else { Text("暂无数据") } } .onAppear { do { datas = try Bundle.main.decode(filename: "movieData1.json") } catch { // 预览时如果解码失败可以打印错误,不会直接崩溃 print("解码失败:\(error)") // 预览时可以补充测试假数据保证预览正常 #if DEBUG datas = [Movie1( MOVIE_ID: "test001", NAME: "测试影片", ALIAS: nil, ACTORS: "测试演员", COVER: nil, DIRECTORS: nil, DOUBAN_SCORE: nil, DOUBAN_VOTES: nil, GENRES: nil, IMDB_ID: nil, LANGUAGES: nil, MINS: nil, OFFICIAL_SITE: nil, REGIONS: nil, RELEASE_DATE: nil, SLUG: nil, STORYLINE: nil, TAGS: nil, YEAR: nil, ACTOR_IDS: nil, DIRECTOR_IDS: nil )] #endif } } } }
如果你的JSON根节点是单个对象而非数组,将datas的类型改为Movie1?即可。
内容的提问来源于stack exchange,提问作者Hannah
相关产品推荐
相关产品推荐

