SwiftUI注册功能Preview崩溃求助:数据处理代码引发异常
SwiftUI注册功能Preview崩溃问题解决
崩溃根源分析
- JSON解码类型不匹配:你的
AccessibleData.json中,sex字段是字符串格式(如"true"),age字段是字符串格式(如"20"),但Student结构体中对应的sex是Bool类型、age是Int类型。JSONDecoder无法自动将字符串转换为Bool/Int,导致load函数触发fatalError,直接崩溃。 - 全局变量初始化触发崩溃:
AccessibleGroup是全局变量,Preview启动时会立即执行load("AccessibleData.json"),解码失败直接终止进程,所以即使没点击注册按钮,Preview也会崩溃。 - 逻辑错误(非崩溃但影响功能):
authenticateUser函数中,Vertify = true被写在判断分支外,会强制将验证状态设为true,导致后续逻辑失效。
修复步骤
1. 修正JSON数据类型
修改AccessibleData.json,将sex改为布尔值(移除引号),age改为数字(移除引号):
{ "22371187":{ "name": "周舟舟", "id": "22371187", "sex": true, "birthday": "2003-09-29", "age": 20, "major": "计算机" }, "1":{ "name": "zzh", "id": "1", "sex": true, "birthday": "2003-09-29", "age": 20, "major": "宇航学" }, "22371188":{ "name": "黄小姐", "id": "22371188", "sex": false, "birthday": "2004-09-24", "age": 19, "major": "经济学" }, "22371189":{ "name": "张三", "id": "22371189", "sex": true, "birthday": "2003-07-19", "age": 20, "major": "软件工程" }, "22371190":{ "name": "李四", "id": "22371190", "sex": false, "birthday": "2003-08-23", "age": 20, "major": "数学" }, "22371191":{ "name": "王五", "id": "22371191", "sex": true, "birthday": "2004-09-29", "age": 19, "major": "物理" } }
2. 修复验证逻辑错误
修改authenticateUser函数,将Vertify = true移到匹配成功的分支内,移除强制赋值:
func authenticateUser(stuname: String, stuid: String) { // 重置状态 Vertify = false HadRegi = false if stuid == "" || stuname == "" { alertType = .fail_nil } else if password == "" { alertType = .fail_codenil } else { // 验证学号姓名是否匹配 if let stu = AccessibleGroup[stuid], stu.name == stuname { Vertify = true } // 检查是否已注册 if let stu = UserInfo[stuid], stu.name == stuname { HadRegi = true } if Vertify { if password.count < 8 { alertType = .fail_codeless } else if HadRegi { alertType = .fail_hadregi } else { alertType = .success // 这里可以安全初始化User,因为已经验证过stuid存在于AccessibleGroup let newUser = User( stuName: stuname, stuId: stuid, UserName: "", sex: AccessibleGroup[stuid]!.sex, birthday: AccessibleGroup[stuid]!.birthday, sign_major: AccessibleGroup[stuid]!.major, sign_hobbies: [], sign_mbti: "", sign_major_pre: [], sign_others: [], code: password, new: true, single: nil, inPushToOthers: false, inOthersPushMe: false, age: AccessibleGroup[stuid]!.age ) Regisuccess = true } } else { // 添加验证失败的提示 alertType = .fail_nil } } }
3. 优化load函数避免崩溃(可选)
将load函数的fatalError改为返回可选值,避免解码失败直接崩溃:
func load<T: Decodable>(_ filename: String) -> T? { let data: Data guard let file = Bundle.main.url(forResource: filename, withExtension: nil) else { print("Couldn't find \(filename) in main bundle") return nil } do { data = try Data(contentsOf: file) } catch { print("Couldn't load \(filename) from main bundle:\n\(error)") return nil } do { let decoder = JSONDecoder() return try decoder.decode(T.self, from: data) } catch { print("Couldn't parse \(filename) as \(T.self):\n\(error)") return nil } } // 初始化时处理可选值 var AccessibleGroup: [String: Student] = load("AccessibleData.json") ?? [:]
验证修复
完成上述修改后,Preview应该可以正常启动,点击注册按钮时,学号姓名匹配逻辑会正常工作,不会再崩溃。
内容的提问来源于stack exchange,提问作者zzhzzh
相关产品推荐
相关产品推荐

