2016-04-06 6 views
0

私は2つのクラスを持っています:ContactとBill。連絡先にはBill型の配列があります。NSCodingカスタムオブジェクトの子配列が永続しない

NSKeyedArchiverを使用しても、私の連絡先はうまく存続しますが、Bill配列は保持されません。

私はBillまたはContactを追加するたびに、insertNewObject()メソッドをpersistに呼び出します。ここで

は私のクラスである:ここでは

/* 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

あなたは非オプションとして法案を宣言した場合も同じことが起こるのでしょうか?つまり、 'var bill:[Bill]!'には長さ0の配列があることを確認してください。 'var請求書:[Bill]! = [Bill]() ' –

+0

はい私は変数を非選択肢に変更しましたが、それは私を助けませんでした。 –

+0

NSArray/NSMutableArraysを暗黙の配列ではなく明示的に使用するとどうなりますか?例えばNSArrayとして請求書を宣言しますか?これを行う別の方法は(私が知る限りでは) 'var bill:[Bill] = []'です。私はここで間違っている可能性があります..しかし、明示的に使用して: 'var請求書:NSArray'は最後の手段です –

答えて

0

を呼び出しは()で必要とされるでsuper.initします直列化可能クラスのinitメソッド

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

はリンゴのdevのドキュメント(Objective-Cの中)からのガイドです:あなたはinitWithCoderから自己を返す必要があります

ディスカッション:.あなたは 復号後に別のオブジェクトを代入する必要が 高度なニーズを持っている場合は、awakeAfterUsingCoderで行うことができます。

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

彼はコーダー指定イニシャライザーを使用しています。それがなければ、彼は議定書に同意しないのでコンパイルすることができないでしょう。第2に、コードはObj-Cではなく迅速にあります。 –

+0

私はスーパーへの呼び出しを指摘するために投票しています。 –

関連する問題