Reputation: 911
I have a Core Data entity (type) called NoteEntity. It has a managed variable called noteDocument, which is of the custom type NoteDocument (my subclass of NSDocument). I changed its auto-generated NoteEntity+Core Data Properties class so it reads
import Foundation
import CoreData
extension NoteEntity {
@NSManaged var noteDocument: NoteDocument? // changed
@NSManaged var belongsTo: NSSet?
}
so that noteDocument is of type NoteDocument instead of NSObject. The NoteDocument class does implement NSCoding, as follows:
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")
}
What I want to be able to do is find the noteEntity entities in the managed context with a given noteDocument value. So I run this code (passing it a parameter theNote that corresponds to a noteDocument that I know exists in the managed context):
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)")
}
but it returns no entries. If I comment out the predicate, I get all the NoteEntity values in the database, but with the predicate in there I get nothing. Clearly something is wrong with the search I'm trying to do in the predicate. I think it's because the value is a Transformable, but I'm not sure where to go from there. I know you can't run fetch requests on the members of Transformable arrays, but is it not possible to run fetch requests on single Transformable attributes? If it isn't, what alternatives exist?
EDIT: The NoteDocument class includes a lot more than the NSCoding. As I said, it's an NSDocument subclass. The NSCoding uses a URL as its key because that's the "primary key" for the NoteDocument class - it's what initializes the class. Here is the rest of the class, not including the NSCoding above:
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)
}
}
Upvotes: 4
Views: 591
Reputation: 119031
In the code you show that the only thing you're coding is a URL. In this case it makes much more sense and provides more utility to use a plain string in the entity to store the URL and to add a transient attribute (or create a wrapper class to combine the entity and document) for the document. In this way you can use the URL in the predicate and it's easy to build the predicate from a document. Storing the document as a transformable isn't helping you in any way it seems.
Upvotes: 1