iOS/Swift:图片存入CoreData失败致App崩溃问题求助
你遇到的这个崩溃根源其实很明显——你把转好的二进制数据又转成了字符串,导致CoreData收到的类型和它期望的完全不符,直接触发了类型错误异常。
先回顾下你拿到的错误提示:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "weatherIcon"; desired type = NSData; given type = Swift._NSContiguousString;
再看你代码里的关键错误行:
let iconData = NSData(data: UIImageJPEGRepresentation(icon, 1.0)!) forecast.setValue("\(iconData)", forKey: "weatherIcon")
这里的"\(iconData)"是把NSData对象转成了它的字符串描述(类似<1a2b3c4d ...>这种文本),而不是真正的二进制数据,这和CoreData中weatherIcon属性设定的Binary Data类型完全不匹配,自然就崩溃了。
修复方案:直接存储二进制数据,不要做字符串插值
只需要把那行错误代码改成直接传入iconData即可,另外建议用Swift原生的Data类型替代NSData,同时用可选绑定避免强制解包的风险:
// 用可选绑定处理UIImageJPEGRepresentation的可选返回值,避免崩溃 if let iconData = UIImageJPEGRepresentation(icon, 1.0) { forecast.setValue(iconData, forKey: "weatherIcon") } else { // 这里可以处理图片转Data失败的情况,比如设置默认图或者打印日志 print("Failed to convert icon to binary data") }
额外优化建议
你代码里的forecastInfo是[String]数组,目前用"\(forecastInfo)"转成字符串存储其实不太规范:
forecast.setValue("\(forecastInfo)", forKey: "forecastDetails")
如果想更优雅地存储数组,你可以把CoreData里forecastDetails的属性类型改成:
- 选择
Array,元素类型设为String - 或者选择
Transformable
这样就能直接存储forecastInfo数组,取出来的时候也不需要再解析字符串,直接用数组类型即可。
修改后的完整代码示例
let appDelegate = UIApplication.shared.delegate as! AppDelegate let context = appDelegate.persistentContainer.viewContext let forecast = NSEntityDescription.insertNewObject(forEntityName: "Forecast", into: context) // 直接存储数组(前提是forecastDetails属性已设为Array<String>或Transformable) forecast.setValue(forecastInfo, forKey: "forecastDetails") // 安全存储图片二进制数据 if let iconData = UIImageJPEGRepresentation(icon, 1.0) { forecast.setValue(iconData, forKey: "weatherIcon") } else { print("Icon conversion failed") } do { try context.save() print("Forecast saved successfully") } catch { // 打印具体错误信息,方便调试 print("Error saving data: \(error.localizedDescription)") }
这样修改后,CoreData就能接收到正确类型的数据,不会再出现崩溃问题了。
内容的提问来源于stack exchange,提问作者RochNoure

