当 Swift 的结构体遇上 NSCoding

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看180 回复回复1 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 180|回复: 1
收起左侧

当 Swift 的结构体遇上 NSCoding

[复制链接]
young 发表于 2016-7-29 16:43:00 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
昨天在写一个 Model,需要用到 NSCoding 序列化,之前用 Class 是没问题的,但换到Struct 就歇菜了,NSCoding 并不支持 Swift 的结构体。

放狗一搜,找到两种解决方法,这里总结一下:

当 Swift 的结构体遇上 NSCoding

当 Swift 的结构体遇上 NSCoding - 敏捷大拇指 - 当 Swift 的结构体遇上 NSCoding





方法一

为 Struct 增加一个 HelperClass 属性成员(Class),让后让它遵守 NSCoding 协议。接着为结构体添加编码 encode 和解码 decode 的类型方法,这对方法的内部其实是调用了 HelperClass 的 decodeObjectForKey 和 encodeObject 方法。

[Swift] 纯文本查看 复制代码
struct Person {  
  let firstName: String
  let lastName: String
}

extension Person {  
  class HelperClass: NSObject, NSCoding {

    var person: Person?

    init(person: Person) {
      self.person = person
      super.init()
    }

    class func path() -> String {
      let documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).first
      let path = documentsPath?.stringByAppendingString("/Person")
      return path!
    }

    required init?(coder aDecoder: NSCoder) {
      guard let firstName = aDecoder.decodeObjectForKey("firstName") as? String else { person = nil; super.init(); return nil }
      guard let laseName = aDecoder.decodeObjectForKey("lastName") as? String else { person = nil; super.init(); return nil }

      person = Person(firstName: firstName, lastName: laseName)

      super.init()
    }

    func encodeWithCoder(aCoder: NSCoder) {
      aCoder.encodeObject(person!.firstName, forKey: "firstName")
      aCoder.encodeObject(person!.lastName, forKey: "lastName")
    }
  }


使用起来也很简单:

[Swift] 纯文本查看 复制代码
let me = Person(firstName: "Dominik", lastName: "Hauser")

Person.encode(me)

let myClone = Person.decode()

firstNameLabel.text = myClone?.firstName  
lastNameLabel.text = myClone?.lastName 





方法二

定义一个 Protocol,包含两个方法:

  • 从结构体中得到一个 NSDictionary 对象
  • 使用一个 NSDictionary 对象初始化结构体


然后 NSDictionary 就可以使用 NSKeyedArchiver 进行序列化。这种方法的优点是:每个遵守该协议的结构体都可以被序列化,下面的代码将结构体归档到 NSUserDefaults 中。

[Swift] 纯文本查看 复制代码
// MARK: -
// MARK: Property list conversion protocol

protocol PropertyListReadable {  
    func propertyListRepresentation() -> NSDictionary
    init?(propertyListRepresentation:NSDictionary?)
}

func extractValuesFromPropertyListArray<T:PropertyListReadable>(propertyListArray:[AnyObject]?) -> [T] {  
    guard let encodedArray = propertyListArray else {return []}
    return encodedArray.map{$0 as? NSDictionary}
        .flatMap{T(propertyListRepresentation:$0)}
}

func saveValuesToDefaults<T:PropertyListReadable>(newValues:[T], key:String) {  
    let encodedValues = newValues.map{$0.propertyListRepresentation()}
    NSUserDefaults.standardUserDefaults()
        .setObject(encodedValues, forKey:key)
}

// MARK: -
// MARK: Coordinates

struct Coordinate {  
    let x:Double
    let y:Double
    let z:Double

    init(_ x: Double, _ y: Double, _ z: Double) {
        self.x = x
        self.y = y
        self.z = z
    }
}

extension Coordinate: PropertyListReadable {  
    func propertyListRepresentation() -> NSDictionary {
        let representation:[String:AnyObject] = ["x":self.x, "y":self.y, "z":self.z]
        return representation
    }

    init?(propertyListRepresentation:NSDictionary?) {
        guard let values = propertyListRepresentation else {return nil}
        if let xCoordinate = values["x"] as? Double,
            yCoordinate = values["y"] as? Double,
            zCoordinate = values["z"] as? Double {
                self.x = xCoordinate
                self.y = yCoordinate
                self.z = zCoordinate
        } else {
            return nil
        }
    }
}





作者:chengway


都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。您的赞赏是我前进的方向。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

评分

参与人数 1金钱 +10 收起 理由
Anewczs + 10 推送上首页了~分享到朋友圈微博QQ空间吧~.

查看全部评分

女汉子 发表于 2016-7-30 02:50:02 | 显示全部楼层
学习了,谢谢楼主!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

淘帖专辑
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表