为何带默认返回值的recurringBase变量会返回nil引发崩溃?
recurringBase已设默认返回值仍出现nil崩溃 代码中localTaskObject.recurringBase的getter已设置默认返回.none,但switch语句仍出现25次Unexpectedly found nil while unwrapping an Optional value崩溃,疑问是该变量为何会返回nil。
崩溃的switch语句:
switch localTaskObject.recurringBase { case .weekly: pickerView.selectRow((components.weekday ?? 1) - 1, inComponent: 0, animated: true) case .monthly: pickerView.selectRow((components.day ?? 1) - 1, inComponent: 0, animated: true) case .yearly: pickerView.selectRow((components.month ?? 1) - 1, inComponent: 0, animated: true) pickerView.selectRow((components.day ?? 1) - 1, inComponent: 1, animated: true) default: break }
recurringBase的定义:
@objc(Task) public class Task: NSManagedObject { ... // 其他代码 var recurringBase : RecurringBase { set { let toSet = newValue.rawValue if toSet != primitiveValue(forKey: keyRecurringBase) as? String { willChangeValue(forKey: keyRecurringBase ) setPrimitiveValue(toSet, forKey: keyRecurringBase) didChangeValue(forKey: keyRecurringBase) } } get { if let storedString = primitiveValue(forKey: keyRecurringBase) as? String, let recurring = RecurringBase(rawValue: storedString) { return recurring } return .none } } }
崩溃日志说明:
崩溃提示为Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value,触发点为上述switch语句的行。
原因分析及解决方案
最可能的原因:localTaskObject本身为nil
你看到的崩溃并非recurringBase返回nil,而是localTaskObject是可选类型(Task?),你直接访问它的recurringBase属性时未做安全解包,导致nil解包崩溃。
解决方案:
先对localTaskObject进行安全解包:
guard let localTask = localTaskObject else { return } switch localTask.recurringBase { case .weekly: pickerView.selectRow((components.weekday ?? 1) - 1, inComponent: 0, animated: true) case .monthly: pickerView.selectRow((components.day ?? 1) - 1, inComponent: 0, animated: true) case .yearly: pickerView.selectRow((components.month ?? 1) - 1, inComponent: 0, animated: true) pickerView.selectRow((components.day ?? 1) - 1, inComponent: 1, animated: true) default: break }
其他可能性排查
Core Data实体属性不匹配
检查Core Data模型中keyRecurringBase对应的属性是否为String类型,且与RecurringBase的rawValue类型一致。若模型属性类型错误,可能导致primitiveValue(forKey:)返回异常值,但你的getter已处理该情况,所以此原因概率较低。Objective-C桥接漏洞
由于Task继承自Objective-C的NSManagedObject,可能存在通过Objective-C代码绕过Swift类型检查,给recurringBase设置nil的情况。可在getter中添加断言验证返回值:
get { let result: RecurringBase if let storedString = primitiveValue(forKey: keyRecurringBase) as? String, let recurring = RecurringBase(rawValue: storedString) { result = recurring } else { result = .none } assert(result != nil, "recurringBase 不应为nil") return result }
内容的提问来源于stack exchange,提问作者Dave

