简体   繁体   English

快速使用非可选对象将其视为可选

[英]Using non-optional object while swift consider it optional

I have a coreData NSManagedObject as follows: 我有一个coreData NSManagedObject ,如下所示:

public class Records: NSManagedObject {
    @NSManaged public var uid: String
    @NSManaged public var datetime: Date
}

In addition, I have a helper to retrieve the record by UID: 此外,我还有一个帮助程序可通过UID检索记录:

func getRecordByUid(uid: String) -> Records!{
    do {
        let fetchRequest : NSFetchRequest<Records> = Records.createFetchRequest()
        fetchRequest.predicate = NSPredicate(format: "uid = %@", uid)
        let result: [Records] = try container.viewContext.fetch(fetchRequest)
        return result.first
    } catch {
        print(error.localizedDescription)
        return nil
    }
}

Now, in my view controller I used a core-data object as non-optional (for adding new record or editing existing record purpose) as described below: 现在,在我的视图控制器中,我将核心数据对象用作非可选对象(用于添加新记录或编辑现有记录的目的),如下所述:

class AddRecordViewController: UIViewController {

    var container: NSPersistentContainer!
    var record: Records!
    var currentUid = ""
    @IBOutlet weak var dateTextField: PickerBasedTextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        // initialise core data
        container = NSPersistentContainer(name: "MyModel")
        container.loadPersistentStores { (storeDescription, error) in
            self.container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

            if let error = error {
                print("Unsolved error \(error.localizedDescription)")
            }
        }

        if let existingRecord = Facade.share.model.getRecordByUid(uid: currentUid) {
            record = existingRecord
        } else {
            record = Records(context: self.container.viewContext)
        }

        // datePicker
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        dateTextField.text = formatter.string(from: record.datetime)

        ...
    }
}

The problem is that it cause an error in dateTextField.text = ... line, because it thinks the record is optional, however it isn't a case: 问题在于,它会导致dateTextField.text = ...行中出现错误,因为它认为record是可选的,但事实并非如此:

(lldb) po record
▿ Optional<Records>

Fatal error: Unexpectedly found nil while unwrapping an Optional value

What should I do? 我该怎么办?

I think that dateTextField is probably nil, and the fatal error is related to it. 我认为dateTextField可能为零,并且致命错误与之相关。 Either that, or Records(context: self.container.viewContext) is a failable initializer that returns a nil object in some cases. 要么Records(context: self.container.viewContext)是一个失败的初始化程序,在某些情况下会返回nil对象。

I think your code would behave much better if you wrapped the fetch with the create into one method that always returns an object. 我认为,如果将带有create的抓取包装到一个始终返回对象的方法中,则代码的性能会更好。

Something like 就像是

func getOrCreateRecord(uid: String) -> Records{
    var record: Records?
    do {
        let fetchRequest : NSFetchRequest<Records> = Records.createFetchRequest()
        fetchRequest.predicate = NSPredicate(format: "uid = %@", uid)
        let result: [Records] = try container.viewContext.fetch(fetchRequest)
        record = result.first
    } catch {
        print(error.localizedDescription)
    }

    return record ?? Records(context: container.viewContext)
}

There still might be an issue with the text field but I still think it makes sense to create a wrapper method for this logic. 文本字段可能仍然存在问题,但是我仍然认为为该逻辑创建包装方法是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM