ios - NSCoding 自定义对象子数组未持久化

标签 ios swift

我有两个类:Contact 和 Bill。 Contact 有一个类型为 Bill 的数组。

当我坚持使用 NSKeyedArchiver 时,我的联系人保持得很好,但是,它不会保持 Bill 数组。

每次添加账单或联系人时,我都会在持久化中调用 insertNewObject() 方法。

这是我的类(class):

/* 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 retrieveContracts(){
        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")
    }
}

最佳答案

这里是来自苹果开发文档的指南(在 Objective-C 中):

Discussion You must return self from initWithCoder:. If you have an advanced need that requires substituting a different object after decoding, you can do so in 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;
}

关于ios - NSCoding 自定义对象子数组未持久化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36458499/

相关文章:

ios - UITableView 和单元格重用

ios - 按下后退按钮时 UIView 动画不起作用

ios - react-native 中的组件样式在应用程序中呈现不一致

ios - 强制触摸后选择菜单项时不调用选择器

swift - 滚动后在 Collection View 单元格上随机显示事件指示器

ios - 初始化前使用的常量 'error'

ios - 如何在文本字段 swift ios 中输入 4 个字母后添加功能

iphone - 重新进入前景后 UINavigationBar 高度降低

ios - 如何在今天的小部件扩展中使用核心数据?

swift - 重置和更改 SKActions 的速度