CoreData Swift and transient attribute getters

后端 未结 4 1679
我在风中等你
我在风中等你 2020-12-02 20:57

Any advice on implementing calculated attributes when using Core Data in Swift?

with the generated ManagedObject class, I tried to override the getter but I get the

相关标签:
4条回答
  • 2020-12-02 21:29

    First, in the data model create a transient attribute (section). Because it is transient, it is not physically stored and thus not stored in the managed object context.

    The section attribute is shown here:

    enter image description here

    The entity is shown here:

    enter image description here

    The class NSManagedObject subclass should have computed 'section' attribute. The NSManagedObject subclass demonstrating how to accomplish this is shown here:

    class Number: NSManagedObject {
    
        @NSManaged var number: NSNumber
    
        var section: String? {
            return number.intValue >= 60 ? "Pass" : "Fail"
        }
    }
    

    Then you must set sectionForKeyPath in the NSFetchedResultsController initializer to be the transient attribute key in the data model and the cache name if desired.

    override func viewDidLoad() {
            super.viewDidLoad()
    
            fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: "section", cacheName: "Root")
            fetchedResultsController?.delegate = self
            fetchedResultsController?.performFetch(nil)
    
            tableView.reloadData()
    }
    
    func fetchRequest() -> NSFetchRequest {
    
        var fetchRequest = NSFetchRequest(entityName: "Number")
        let sortDescriptor = NSSortDescriptor(key: "number", ascending: false)
    
        fetchRequest.predicate = nil
        fetchRequest.sortDescriptors = [sortDescriptor]
        fetchRequest.fetchBatchSize = 20
    
        return fetchRequest
    }
    

    The result is a UITableViewController with grades sorted by pass or fail dynamically:

    enter image description here

    I made a sample project that can be found on GitHub.

    0 讨论(0)
  • 2020-12-02 21:36

    Remove the NSManaged attribute.

    0 讨论(0)
  • 2020-12-02 21:38

    I have solved this in Swift with an extension, so there is no need to subclass the NSManagedObject and I don't have to generate class files for my models.

    So for the above example with class Number, create a file Number+Section.swift you can load the transient property value like this in awakeFromFetch

    import Foundation    
    extension Number {
        public override func awakeFromFetch() {
            super.awakeFromFetch()
            section = number.intValue >= 60 ? "Pass" : "Fail"
        }
    }
    

    I found this way of loading transient fields in Apple's Core Data programming guide.

    awakeFromFetch is invoked when an object is reinitialized from a persistent store (during a fetch). You can override awakeFromFetch to, for example, establish transient values and other caches.

    0 讨论(0)
  • 2020-12-02 21:40

    "Transient" and "computed" in the sense you mean are different things and are mutually exclusive.

    Transient means that the value is stored in memory on the object graph. Computed means that the value is stored nowhere and is calculated in the getter. Both are distinct from the classic non-transient attribute which is stored on the object graph and is saved to disk.

    @NSManaged can only be applied to attributes that have a slot in your managed object model.

    0 讨论(0)
提交回复
热议问题