2016-04-06 5 views
0

Ich habe zwei Klassen: Kontakt und Bill. Kontakt hat eine Reihe von Typ Bill.NSCoding benutzerdefinierte Objekt Kind Array nicht persistent

Wenn ich mit NSKeyedArchiver beharrlich bleiben meine persistent gut erhalten, aber es bleibt nicht das Bill-Array.

Jedes Mal, wenn ich eine Rechnung oder einen Kontakt hinzufügen, rufe ich die insertNewObject() Methode in persist auf. meine Klassen

sind hier:

/* Persist.swift */ 
import Foundation 

class Persist { 

    static let sharedInstance = Persist() 

    let delegate = UIApplication.sharedApplication().delegate as! AppDelegate 
    var contactsFilePath : String { 
     let manager = NSFileManager.defaultManager() 
     let url = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL 
     return url.URLByAppendingPathComponent("\(delegate.userId):objectsArrayz").path! 
    } 

    func insertNewObject(){ 
     NSKeyedArchiver.archiveRootObject(delegate.contacts!, toFile: contactsFilePath) 

    } 

    func retreieveContracts(){ 
     if let array = NSKeyedUnarchiver.unarchiveObjectWithFile(contactsFilePath) as? [Contact] { 
      delegate.contacts = array 
     } 
    } 

    func deleteContact(rowNum : Int){ 
     delegate.contacts!.removeAtIndex(rowNum) 
     NSKeyedArchiver.archiveRootObject(delegate.contacts!, toFile: contactsFilePath) 
    } 

/* Contact.swift */  
import Foundation 

class Contact : NSObject, NSCoding{ 

    var image : UIImage? 
    var firstName : String? 
    var lastName : String? 
    var email : String? 
    var phoneNumber : String? 
    var address : String? 
    var bills : [Bill]? 

    init(image: UIImage, firstName : String, lastName : String, email : String, phoneNumber : String, address : String, bills : [Bill]) { 
     self.image = image 
     self.firstName = firstName 
     self.lastName = lastName 
     self.email = email 
     self.phoneNumber = phoneNumber 
     self.address = address 
     self.bills = bills 
    } 

    // MARK: NSCoding 

    required convenience init?(coder decoder: NSCoder) { 
     guard let image = decoder.decodeObjectForKey("image") as? UIImage, 
      let firstName = decoder.decodeObjectForKey("firstName") as? String, 
      let lastName = decoder.decodeObjectForKey("lastName") as? String, 
      let email = decoder.decodeObjectForKey("email") as? String, 
      let phoneNumber = decoder.decodeObjectForKey("phoneNumber") as? String, 
      let address = decoder.decodeObjectForKey("address") as? String, 
      let bills = decoder.decodeObjectForKey("bills") as? [Bill] 
     else { 
       return nil 
     } 

     self.init(
      image: image, 
      firstName: firstName, 
      lastName : lastName, 
      email : email, 
      phoneNumber : phoneNumber, 
      address : address, 
      bills : bills 

     ) 
    } 

    func encodeWithCoder(coder: NSCoder) { 
     coder.encodeObject(self.image, forKey: "image") 
     coder.encodeObject(self.firstName, forKey: "firstName") 
     coder.encodeObject(self.lastName, forKey: "lastName") 
     coder.encodeObject(self.email, forKey: "email") 
     coder.encodeObject(self.phoneNumber, forKey: "phoneNumber") 
     coder.encodeObject(self.address, forKey: "address") 
     coder.encodeObject(self.bills, forKey: "bills") 
    } 
} 


/* Bill.swift*/ 
import Foundation 

class Bill : NSObject, NSCoding{ 

    var service : String? 
    var subtotal : Double? 
    var taxes : Double? 
    var total : Double? 


    init(service : String, subtotal : Double, taxes : Double, total: Double) { 
     self.service = service 
     self.subtotal = subtotal 
     self.taxes = taxes 

    } 

    // MARK: NSCoding 

    required convenience init?(coder decoder: NSCoder) { 

     guard let service = decoder.decodeObjectForKey("service") as? String, 
      let subtotal = decoder.decodeObjectForKey("subtotal") as? Double, 
      let taxes = decoder.decodeObjectForKey("taxes") as? Double, 
      let total = decoder.decodeObjectForKey("total") as? Double 

      else { 
       return nil 
     } 


     self.init(
      service: service, 
      subtotal: subtotal, 
      taxes: taxes, 
      total: total 

     ) 
    } 

    func encodeWithCoder(coder: NSCoder) { 
     coder.encodeObject(self.service, forKey: "service") 
     coder.encodeObject(self.subtotal, forKey: "subtotal") 
     coder.encodeObject(self.taxes, forKey: "taxes") 
     coder.encodeObject(self.total, forKey: "total") 
    } 
} 
+0

Geschieht das gleiche, wenn Sie Rechnungen als nicht optional deklarieren? h. 'var bills: [Bill]!' Seien Sie einfach sicher, dass dort z. 'var Rechnungen: [Bill]! = [Bill]() ' –

+0

Ja, ich habe meine Variablen in Nicht-Optionen geändert, aber es hat mir nicht geholfen. –

+0

Und was - wenn Sie NSArray/NSMutableArrays explizit anstelle von implizierten Arrays verwenden? z.B. Rechnungen als NSArray deklarieren? Eine andere Möglichkeit dies zu tun (so weit ich weiß) ist: 'var bills: [Bill] = []'. Ich könnte mich hier irren. Aber explizit mit: 'var bills: NSArray' ist ein letzter Ausweg –

Antwort

0

Ein Aufruf super.init() in dem erforderlichen Init-Methode der serialisierbaren Klasse.

Snippet von Bill.swift

required init?(coder decoder: NSCoder) { 
     super.init() 
     service = decoder.decodeObjectForKey("service") as? String 
     subtotal = decoder.decodeObjectForKey("subtotal") as? Double 
     taxes = decoder.decodeObjectForKey("taxes") as? Double 
     total = decoder.decodeObjectForKey("total") as? Double 
     services = decoder.decodeObjectForKey("services") as? [Service] 
    } 
1

Hier ist eine Anleitung aus dem Apple-Entwickler-Dokumentation (in Objective-c):

Diskussion Sie müssen sich selbst von initWithCoder zurückkehren :. Wenn Sie eine erweiterte Notwendigkeit haben, die ein anderes Objekt nach Decodierung erfordert ersetzen, können Sie dies in awakeAfterUsingCoder tun:

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html

- (void)encodeWithCoder:(NSCoder *)coder { 
    [super encodeWithCoder:coder]; 
    // Implementation continues 
} 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    if (self) { 
     _firstName = [coder decodeObjectForKey:ASCPersonFirstName]; 
     _lastName = [coder decodeObjectForKey:ASCPersonLastName]; 
     _height = [coder decodeFloatForKey:ASCPersonHeight]; 
    } 
    return self; 
} 
+0

Er verwendet den coder designed initialiser. Ohne ihn wäre er nicht in der Lage zu kompilieren, da dies das Protokoll nicht bestätigen würde. Zweitens ist der Code in swift, nicht Obj-C. –

+0

Ich stimme dir zu, dass du auf den Anruf von Super hingewiesen hast. –

Verwandte Themen