CoreData Swift和瞬态属性getter

时间:2014-09-21 15:04:41

标签: core-data swift

在Swift中使用Core Data时有关实现计算属性的任何建议吗?

使用生成的ManagedObject类,我试图覆盖getter,但是我收到了错误:

  

'NSManaged'不允许使用计算属性

这意味着您无法覆盖瞬态(计算)属性的getter。

在下面的代码示例中,dateDue被定义为我模型中的瞬态属性。

请注意@NSManaged行是由Xcode生成的 - 不是我添加的。

@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!
    }

}

4 个答案:

答案 0 :(得分:46)

首先,在数据模型中创建一个瞬态属性(section)。因为它是瞬态的,所以它不是物理存储的,因此不存储在托管对象上下文中。

此处显示section属性:

enter image description here

此处显示实体:

enter image description here

类NSManagedObject子类应该具有计算'section'属性。演示如何完成此任务的NSManagedObject子类如下所示:

class Number: NSManagedObject {

    @NSManaged var number: NSNumber

    var section: String? {
        return number.intValue >= 60 ? "Pass" : "Fail"
    }
}

然后,您必须将NSFetchedResultsController初始值设定项中的sectionForKeyPath设置为数据模型中的瞬态属性键,并根据需要设置缓存名称。

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
}

结果是UITableViewController,其成绩按动态传递或失败排序:

enter image description here

我制作了一个可以在GitHub上找到的示例项目。

答案 1 :(得分:7)

"瞬态"和"计算"从某种意义上说,你的意思是不同的东西,是相互排斥的。

瞬态意味着该值存储在对象图上的内存中。计算意味着该值无处存储并在getter中计算。两者都不同于经典的非瞬态属性,它存储在对象图上并保存到磁盘中。

@NSManaged只能应用于托管对象模型中有插槽的属性。

答案 2 :(得分:1)

删除NSManaged属性。

答案 3 :(得分:1)

我已经在Swift中使用扩展名解决了这个问题,因此无需继承NSManagedObject的类,也不必为模型生成类文件。

因此,对于以上带有类Number的示例,创建一个文件Number+Section.swift,您可以在awakeFromFetch中加载这样的瞬态属性值

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

我发现这种在Apple Core Data programming guide中加载瞬态字段的方式。

  从对象重新初始化对象时,将调用

awakeFromFetch。   持久性存储(在获取期间)。您可以将awakeFromFetch覆盖为   例如,建立瞬态值和其他缓存。