2016-07-24 14 views
4

Ich habe eine Core Data-Entität (Typ) namens NoteEntity. Es hat eine verwaltete Variable namens noteDocument, die vom benutzerdefinierten Typ NoteDocument (meine Unterklasse von NSDocument) ist. Ich änderte seine automatisch generierte NoteEntity + Core Data Properties Klasse so liest esAbrufanforderung für einzelnes transformierbares Attribut (Swift)

import Foundation 
import CoreData 

extension NoteEntity { 

    @NSManaged var noteDocument: NoteDocument? // changed 
    @NSManaged var belongsTo: NSSet? 

} 

so dass noteDocument vom Typ NoteDocument ist anstelle von NSObject. Die NoteDocument Klasse nicht implementiert NSCoding wie folgt:

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") 
} 

Was ich will, ist zu tun, um die Lage sein, die noteEntity Einheiten in dem verwalteten Zusammenhang mit einem bestimmten noteDocument Wert zu finden. So betreibe ich diesen Code (einen Parameter theNote vorbei, die zu einem noteDocument entspricht, die ich kenne in dem verwalteten Kontext vorhanden ist):

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)") 
    } 

aber es gibt keine Einträge. Wenn ich das Prädikat auskommentiere, bekomme ich alle NoteEntity-Werte in der Datenbank, aber mit dem Prädikat da drin bekomme ich nichts. Offensichtlich stimmt etwas nicht mit der Suche, die ich im Prädikat machen will. I denke, es ist, weil der Wert ist ein Transformable, aber ich bin mir nicht sicher, wo ich von dort gehen soll. Ich weiß, dass Sie keine Abrufanforderungen für die Mitglieder von Transformable-Arrays ausführen können, aber ist es nicht möglich, Abrufanforderungen für einzelne transformierbare Attribute auszuführen? Wenn nicht, welche Alternativen gibt es?

EDIT: Die NoteDocument-Klasse enthält viel mehr als das NSCoding. Wie gesagt, es ist eine NSDocument-Unterklasse. Das NSCoding verwendet eine URL als Schlüssel, da dies der "Primärschlüssel" für die NoteDocument-Klasse ist - es initialisiert die Klasse. Hier ist der Rest der Klasse, ohne die NSCoding oben:

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) 
} 


} 
+1

Möchten Sie Dokumente oder URLs vergleichen? – Willeke

+0

Ich versuche, Dokumentobjekte (der Klasse NoteDocument, welche Unterklassen NSDocument) zu vergleichen. Soll ich das NSCoding entsprechend ändern? –

+0

Verwenden Sie den SQLite-Speicher? – Willeke

Antwort

1

Im Code, den Sie zeigen, dass das einzige, was Sie Codierung eine URL ist. In diesem Fall ist es viel sinnvoller und nützlicher, eine einfache Zeichenfolge in der Entität zu verwenden, um die URL zu speichern und ein Übergangsattribut (oder eine Wrapper-Klasse zum Kombinieren der Entität und des Dokuments) für das Dokument hinzuzufügen. Auf diese Weise können Sie die URL im Prädikat verwenden und das Prädikat aus einem Dokument erstellen. Das Dokument als transformierbar zu speichern, hilft Ihnen in keiner Weise, wie es scheint.

+0

Siehe oben Bearbeiten. Ich versuche, das gesamte Dokument zu speichern, damit Änderungen am Dokument (insbesondere aber nicht nur an der noteText-Variable) im permanenten Speicher (und nicht nur im Dateisystem) gespeichert werden können. Die URL war nur der Schlüssel, den ich für den NSCoding-Teil verwendet habe. Mir ist klar, dass das mein Problem ist, aber ich bin mir nicht sicher, was ich anders machen soll. Die meisten Beispiele, die ich von NSCoding gesehen habe, tun etwas in der Art: nimm ein einzelnes Attribut als Schlüssel, das in den Laden geht und lass es so. Gibt es eine bessere Möglichkeit, das Transformable zu implementieren? –

+0

meine Antwort steht - in Kerndaten transformierbar erhalten Sie nur, was durch Ihre 'NSCoding'-Implementierung gespeichert wird. Das gesamte Dokument wird nicht im persistenten Speicher gespeichert. Warum willst du sogar 2 verschiedene Kopien der gleichen Sache gespeichert? – Wain

+0

Nun, ich hoffe, dass ein relationaler Datenbank-basierter Speicher schneller von der Festplatte geladen werden kann als der Festplatten-/Sekundärspeicher. Damit würde ich das Datum der Version im Dateisystem gegenüber dem persistenten Speicher überprüfen und das Dokument nur aus dem Dateisystem laden, wenn es aktueller ist als die Version im Speicher. Ich denke, wenn ich das immer noch tun wollte, wäre es das NSCoding, die note-text- und datumsveränderten Variablen als Schlüssel neben der URL zu codieren? –