美文网首页ios 开发常用swiftiOS学习笔记
关于 NSCoding 和 NSKeyed​Archiver |

关于 NSCoding 和 NSKeyed​Archiver |

作者: SwiftCafe | 来源:发表于2015-11-13 19:46 被阅读522次

    我们在开发应用的时候,经常会进行一些简单数据的存储,比如应用的一些配置信息。关于数据的存储就会用到 NSCoding 的概念,那么我们就来了解一下吧。

    我们存储简单信息,最常用的就是 NSUserDefaults 类,它可以让我们用很方便的形式以键 - 值 的形式存储信息。比如我们可以这样:

    NSUserDefaults.standardUserDefaults().setObject("Swift", forKey: "Book")
    

    使用起来非常简单,当我们需要使用这个存储的值的时候,我们可以这样获取:

    NSUserDefaults.standardUserDefaults().objectForKey("Book")
    

    也非常的简单。NSUserDefaults 还提供了一些其他的便捷方法,让我们存储和读取各种类型的值:

    public func setInteger(value: Int, forKey defaultName: String)
    public func setFloat(value: Float, forKey defaultName: String)
    public func setDouble(value: Double, forKey defaultName: String)
    public func setBool(value: Bool, forKey defaultName: String)
    public func setURL(url: NSURL?, forKey defaultName: String)
    

    读取方法:

    public func stringForKey(defaultName: String) -> String?
    public func arrayForKey(defaultName: String) -> [AnyObject]?
    public func dictionaryForKey(defaultName: String) -> [String : AnyObject]?
    public func dataForKey(defaultName: String) -> NSData?
    public func stringArrayForKey(defaultName: String) -> [String]?
    public func integerForKey(defaultName: String) -> Int
    public func floatForKey(defaultName: String) -> Float
    public func doubleForKey(defaultName: String) -> Double
    public func boolForKey(defaultName: String) -> Bool
    public func URLForKey(defaultName: String) -> NSURL?
    
    

    提供的接口非常丰富,那么,还有另外一种情况:

    class Book {
    
        var name:String?
        var image:UIImage?
    
    }
    
    let book = Book()
    NSUserDefaults.standardUserDefaults().setObject(book, forKey: "book")
    
    

    我们如果编译,运行这段代码会有什么结果呢?存储成功? 还是:

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object Samples.Book for key book'
    

    恩,出现了运行时错误,这时因为我们的 Book 类是不能直接存入 NSUserDefaults 的,它需要实现 NSCoding 协议才可以进行这样的操作。

    那么我们来对 Book 类进行一些修改:

    
    class Book: NSObject, NSCoding {
    
        var name:String?
        var image:UIImage?
    
        func encodeWithCoder(aCoder: NSCoder) {
    
        }
    
        override init() {
    
        }
    
        required init?(coder aDecoder: NSCoder) {
    
        }
    
    }
    

    现在, Book 类实现了 NSCoding 协议,我们还没有对它进行具体的实现,只是定义了 NSCoding 的两个协议方法 encodeWithCoder(aCoder: NSCoder)init?(coder aDecoder: NSCoder) 这两个方法用作将这个类进行编码和解码。我们稍后在做说明,接下来,我们就可以将他存储到 NSUserDefaults 中了:

    let book = Book()
    let data = NSKeyedArchiver.archivedDataWithRootObject(book)
    NSUserDefaults.standardUserDefaults().setObject(data, forKey: "book")
    

    我们这里用到了一个中间类 NSKeyedArchiver,先是将 Book 通过 NSKeyedArchiver 编码成了 NSData。 然后再将这个 NSData 存入到 NSUserDefaults 中。

    NSKeyedArchiver 只能对实现了 NSCoding 协议的类进行编码,将它们转换成二进制数据,然后再存入 NSUserDefaults 中。

    这样,NSCodingNSKeyedArchiver 在一起使用,不但能够进行 NSUserDefaults 的存储,还能够进行对象的一些实体化和数据传输操作。

    我们再来看一下实现 NSCoding 的具体方法, encodeWithCoder 为编码方法,用于将对象中的值转换成数据:

    func encodeWithCoder(aCoder: NSCoder) {
    
        if let name = self.name {
    
            aCoder.encodeObject(name, forKey: "name")
    
        }
    
        if let image = self.image {
    
            if let imageData = UIImagePNGRepresentation(image) {
    
                aCoder.encodeObject(imageData, forKey: "image")
    
            }
    
        }
    
    }
    

    相应的,init?(coder aDecoder: NSCoder) 作为解码方法,用于将编码后的数据还原成对象:

    required init?(coder aDecoder: NSCoder) {
    
        self.name = aDecoder.decodeObjectForKey("name") as? String
        if let imageData = aDecoder.decodeObjectForKey("image") as? NSData {
    
           image = UIImage(data: imageData)
    
        }
    
    }
    

    我们注意到,无论是编码和解码方法中,都将 self.image 属性先转换成 NSData 然后再进行编码解码操作。

    我们完整的实现了 NSCoding 协议后,就可以通过 NSKeyedArchiverNSKeyedUnarchiver 将他们自由的存取了:

    let book = Book()
    book.name = "Swift"
    book.image = UIImage(named: "cover")
    let data = NSKeyedArchiver.archivedDataWithRootObject(book)
    NSUserDefaults.standardUserDefaults().setObject(data, forKey: "book")
    

    读取:

    if let bookData = NSUserDefaults.standardUserDefaults().objectForKey("book") as? NSData {
    
        if let book = NSKeyedUnarchiver.unarchiveObjectWithData(bookData) as? Book {
    
            print(book.name!)
    
        }
    
    }
    

    更多精彩内容可关注微信公众号:
    swift-cafe

    相关文章

      网友评论

        本文标题:关于 NSCoding 和 NSKeyed​Archiver |

        本文链接:https://www.haomeiwen.com/subject/safkhttx.html