获取单个可转换属性的请求(Swift)
Posted
技术标签:
【中文标题】获取单个可转换属性的请求(Swift)【英文标题】:Fetch request on single Transformable attribute (Swift) 【发布时间】:2016-07-24 20:37:05 【问题描述】:我有一个名为 NoteEntity 的核心数据实体(类型)。它有一个名为 noteDocument 的托管变量,它是自定义类型 NoteDocument(我的 NSDocument 的子类)。我更改了它的自动生成的 NoteEntity+Core Data Properties 类,所以它显示为
import Foundation
import CoreData
extension NoteEntity
@NSManaged var noteDocument: NoteDocument? // changed
@NSManaged var belongsTo: NSSet?
所以 noteDocument 的类型是 NoteDocument 而不是 NSObject。 NoteDocument 类确实实现了 NSCoding,如下:
required convenience init(coder theDecoder: NSCoder)
let retrievedURL = theDecoder.decodeObjectForKey("URLKey") as! NSURL
self.init(receivedURL: retrievedURL)
func encodeWithCoder(theCoder: NSCoder)
theCoder.encodeObject(fileURL, forKey: "URLKey")
我希望能够在具有给定 noteDocument 值的托管上下文中找到 noteEntity 实体。所以我运行这段代码(向它传递一个参数 theNote,它对应于我知道托管上下文中存在的 noteDocument):
var request = NSFetchRequest(entityName: "NoteEntity")
let notePredicate = NSPredicate(format: "noteDocument == %@", theNote)
request.predicate = notePredicate
print("Text in the NoteEntity with the NoteDocument for "+theNote.filename+":")
do
let notesGathered = try context.executeFetchRequest(request) as? [NoteEntity]
for n in notesGathered!
print (n.noteDocument!.filename)
print (n.noteDocument!.noteText)
catch let error as NSError
print("Could not run fetch request. \(error), \(error.userInfo)")
但它不返回任何条目。如果我注释掉谓词,我会得到数据库中的所有 NoteEntity 值,但如果有谓词,我什么也得不到。显然,我试图在谓词中进行的搜索有问题。我认为这是因为该值是可变形的,但我不确定从那里去哪里。我知道你不能对 Transformable 数组的成员运行 fetch 请求,但是不可能对单个 Transformable 属性运行 fetch 请求吗?如果不是,还有哪些替代方案?
编辑:NoteDocument 类包含的内容远不止 NSCoding。正如我所说,它是一个 NSDocument 子类。 NSCoding 使用 URL 作为其键,因为这是 NoteDocument 类的“主键”——它是初始化类的东西。这是课程的其余部分,不包括上面的 NSCoding:
import Cocoa
class NoteDocument: NSDocument, NSCoding
var filename: String
var noteText: String
var attributes: NSDictionary?
var dateCreated: NSDate?
var dateString: String?
init (receivedURL: NSURL)
self.filename = ""
self.noteText = ""
super.init()
self.fileType = "net.daringfireball.markdown"
self.fileURL = receivedURL
// Try to get attributes, most importantly date-created.
let fileManager = NSFileManager.defaultManager()
do
attributes = try fileManager.attributesOfItemAtPath(fileURL!.path!)
catch let error as NSError
print("The error was: "+String(error))
if let dateCreated = attributes?.fileCreationDate()
// print("dateCreated is "+String(dateCreated!))
// Format the date-created to an appropriate string.
dateString = String(dateCreated)
else
print("Did not find the attributes for "+filename)
if let name = self.fileURL?.lastPathComponent
filename = name
else
filename = "Unnamed File"
noteText = ""
do
noteText = try NSString(contentsOfURL: self.fileURL!, encoding: NSUTF8StringEncoding) as String
catch let error as NSError
print("Error trying to get note file:"+String(error))
// MARK: - Document functions
override class func autosavesInPlace() -> Bool
// print ("autosavesInPlace ran.")
return true
override func dataOfType(typeName: String) throws -> NSData
var outError: NSError! = NSError(domain: "Migrator", code: 0, userInfo: nil)
// Post: Document is saved to a file specified by the user.
outError = NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
if let value = self.noteText.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
// Convert noteText to an NSData object and return that.
return value
print("dataOfType ran.")
throw outError
override func readFromData(data: NSData, ofType typeName: String) throws
// Currently unused; came free with NSDocument.
throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
【问题讨论】:
您要比较文档或网址吗? 我正在尝试比较 Document 对象(属于 NoteDocument 类,它是 NSDocument 的子类)。我应该相应地更改 NSCoding 吗? 你使用 SQLite 存储吗? 我相信是这样 - 目前默认的 CocoaAppCD.storedata 存储,我认为是 SQLite。 【参考方案1】:在代码中,您表明您编码的唯一内容是 URL。在这种情况下,在实体中使用纯字符串来存储 URL 并为文档添加临时属性(或创建包装类以组合实体和文档)会更有意义并提供更多实用程序。通过这种方式,您可以在谓词中使用 URL,并且很容易从文档中构建谓词。将文档存储为可转换文件似乎对您没有任何帮助。
【讨论】:
见上面的编辑。我正在尝试存储整个文档,以便可以将对文档的更改(尤其是但不仅是 noteText 变量)保存在持久存储中(而不仅仅是文件系统)。 URL 只是我用于 NSCoding 部分的密钥。现在我很清楚这就是我的问题所在,但我不确定该怎么做。我见过的大多数 NSCoding 示例都是这样的:将单个属性作为进入 store 的键,然后保持原样。有没有更好的方法来实现可转换? 我的答案是——在可转换的核心数据中,您只能获得NSCoding
实现所保存的内容。整个文档不会保存在持久存储中。为什么你还要保存同一事物的 2 个不同副本?
嗯,我希望基于关系数据库的持久存储的加载速度比硬盘驱动器/辅助内存快。这样我就可以检查文件系统中版本与持久存储的日期修改,并且仅在文件系统比存储中的版本更新时才从文件系统加载文档。我想如果我仍然想这样做,那么做到这一点的方法是让 NSCoding 将注释文本和日期修改变量编码为 URL 旁边的键?
是的,但核心数据存储的唯一好处是部分加载,整个数据集的加载不会更快。如果将所有数据放在同一个可转换对象中,则差异基本上为零。为了提高速度,您应该查看可以保留在内存中的内容以及使用频率较低的数据,以便在明确请求之前无需加载。
公平。没有机会对此进行测试,因为还有a bug 在此期间使程序崩溃,但我想确保获得赏金,并且您的回答是有道理的。我将尝试按照您的建议对 URL 进行编码,如果我决定确实需要将更多 Document 元素放入数据库中,那么我将在 URL 旁边编码更多变量。以上是关于获取单个可转换属性的请求(Swift)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 Swift 的 Core Data 获取非标准(可转换)属性来更新/保存和持久化?
如何在 Swift 中将可转换属性保存到 Core Data
如何使用 Weka API 请求单个属性的输入以遍历决策树?
使用核心数据swift ios获取实体的所有属性到tableview中的行中的标签