Core data coredataswift和transient属性获取程序
在Swift中使用核心数据时,对实现计算属性有何建议 使用生成的ManagedObject类,我试图重写getter,但出现错误: 计算属性上不允许使用“NSManaged” 这意味着您不能覆盖瞬态(计算)属性的getter 在下面的代码示例中,Core data coredataswift和transient属性获取程序,core-data,swift,Core Data,Swift,在Swift中使用核心数据时,对实现计算属性有何建议 使用生成的ManagedObject类,我试图重写getter,但出现错误: 计算属性上不允许使用“NSManaged” 这意味着您不能覆盖瞬态(计算)属性的getter 在下面的代码示例中,dateDue在我的模型中被定义为瞬态属性 请注意,@NSManaged行是由Xcode生成的,不是我添加的 @NSManaged var timeStamp: NSDate @NSManaged var dateDue: String { g
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!
}
}
你所指的“瞬时”和“计算”是不同的东西,是相互排斥的
瞬态意味着该值存储在对象图的内存中。Computed意味着该值不存储在任何地方,而是在getter中计算。两者都不同于存储在对象图上并保存到磁盘的经典非瞬态属性
@NSManaged
只能应用于在托管对象模型中具有插槽的属性。删除NSManaged
属性。首先,在数据模型中创建一个临时属性(部分
)。因为它是暂时的,所以不会物理存储,因此也不会存储在托管对象上下文中
部分
属性如下所示:
class Number: NSManagedObject {
@NSManaged var number: NSNumber
var section: String? {
return number.intValue >= 60 ? "Pass" : "Fail"
}
}
实体如下所示:
class Number: NSManagedObject {
@NSManaged var number: NSNumber
var section: String? {
return number.intValue >= 60 ? "Pass" : "Fail"
}
}
类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
,其等级按通过或失败动态排序:
我制作了一个可以在上找到的示例项目。我已经用Swift解决了这个问题,并提供了一个扩展,因此不需要对NSManagedObject进行子类化,也不必为我的模型生成类文件 因此,对于上面带有class
Number
的示例,创建一个文件Number+节。swift
您可以在awakeFromFetch
import Foundation
extension Number {
public override func awakeFromFetch() {
super.awakeFromFetch()
section = number.intValue >= 60 ? "Pass" : "Fail"
}
}
我在苹果电脑中找到了这种加载瞬态场的方法
awakeFromFetch在从对象重新初始化对象时调用
持久存储(在获取期间)。您可以将awakeFromFetch重写为,
例如,建立瞬态值和其他缓存
它是托管对象模型中的一个属性。为了扩展,我正在尝试复制一个苹果示例程序使用的技术-但是苹果示例是用Objective C编写的-事实上它是用Xcode(master-detail应用程序)交付的模板.是的,但ObjC不执行
@NSManaged
——如果您试图包装底层属性,则不应在此处使用@NSManaged
@NSManaged
告诉编译器将在运行时延迟提供属性实现。在显式提供实现的同时使用@NSManaged
是一种矛盾。好的,谢谢。我将重新讨论删除NSM。让你知道我是如何相处的:)不。对不起,不是这样的。这部分代码是由Xcode生成的,所以我认为是正确的(或者至少是苹果的预期)如果它是暂时的,就不会被管理。因此,要么应用,要么你犯了一个错误,Xcode生成了代码,但你正在编写一个隐藏底层属性的方法,你和代码生成器的想法不同。明白你的意思了吗。我将尝试不使用NSManaged——我想我必须对Xcode生成的内容更加怀疑一点。@DaijDjan完全正确。在这种情况下应该删除。为我工作。:)此解决方案的缺点是必须编辑自动生成的核心数据类。每次重新生成时,都必须重新进行修改。我将节放在扩展类中,但在重新生成类后,我仍然必须从生成的类中删除节。这个答案应该被接受!用日期而不是数字对我来说非常有效。对于每个试图从“DateSectionTitles”苹果示例项目开始按日期实现节分隔的人,一个建议是:遵循以下答案!非常感谢@BluehoundI无法将其与swift 4/iOS 11配合使用。有人有类似的问题吗?@webventil找到了解决办法。需要在属性声明前面添加@objc我认为这个答案没有抓住要点。关键是瞬态核心数据属性仍然会为您生成一个getter和setter。您可以编辑机器生成的核心数据实体文件,使属性为只读而不是复制(即读写),然后在用户可编辑的实体生成文件中写入自己的getter,但任何涉及编辑机器生成文件的内容都不是一个好的解决方案。一个更好的答案可能是:忘记拥有一个暂时的属性。只需在人类可编辑CD生成的文件中创建一个getter,计算值。如果将Codegen设置为“类定义”,则此方法有效。感谢《解决方案核心数据指南》对此进行了清晰的解释。虽然它基本上可以正常工作,但当将NSFetchedResultsController与表视图结合使用时,这不是一个好的解决方案:初始表部分是正确的,但当您更新基础数据时,显然不会再次调用awakeFromFetch。这是一个很好的答案,特别是因为允许避免类生成只是为了有一个瞬态属性!比过去容易多了,谢谢!