CoreData Swift and transient attribute getters

core-data, swift

Solution

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:

The entity is shown 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:

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

Problem

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 error: 'NSManaged' not allowed on computed properties which implies you cannot override the getter for a transient (calculated) attribute. In the code sample below, `dateDue` is defined as a transient attribute in my model. Please note that the @NSManaged lines were generated by Xcode - not added by me. ``` @NSManaged var timeStamp: NSDate @NSManaged var dateDue: String { get { self.willAccessValueForKey("dateDue") var ddtmp = self.primitiveValueForKey("dateDue") as String? self.didAccessValueForKey("dateDue") if (ddtmp == nil) { let calendar = NSCalendar.currentCalendar() let components = calendar.components((NSCalendarUnit.YearCalendarUnit | NSCalendarUnit.MonthCalendarUnit ) , fromDate: self.timeStamp) ddtmp = "\(components.year * 1000 + components.month)" self.setPrimitiveValue(ddtmp, forKey: "dateDue") } return ddtmp! } } ```

Original source