SwiftでオブジェクトをNSUserDefaultsに保存する

環境:swift2.1

NSUserDefaultsにオブジェクトのまま保存したかったが、保存できるオブジェクトはNSArray, NSDictionary, NSString, NSNumber, NSDate ,NSDataに限られていた。

調べたところ、オブジェクトをNSDataに変換できることがわかった。
NSDataにできればNSUserDefaultsにも保存できる。

実装方法

  • 対象のオブジェクトにNSCodingプロトコルのデコードメソッドinit?(coder aDecoder: NSCoder)エンコードメソッドencodeWithCoder(aCoder: NSCoder)を実装する
  • 保存時はNSKeyedArchiver.archivedDataWithRootObject:でオブジェクトをNSDataに変換
  • 読み込み時はNSKeyedUnarchiver.unarchiveObjectWithData:NSDataからオブジェクトに変換

以下サンプルコード

struct UserDefaultsKey {
    
    static let User = "user"
}

struct SerializedKey {
    
    static let UserId   = "userId"
    static let Uuid     = "uuid"
    static let NickName = "nickName"
}

class User: NSObject, NSCoding {
    
    var userId: Int
    var uuid: String
    var nickName: String?
    
    init(userId: Int, uuid: String, nickName: String? = nil) {
        self.userId = userId
        self.uuid = uuid
        self.nickName = nickName
    }

    required init?(coder aDecoder: NSCoder) {
        
        self.userId   = aDecoder.decodeObjectForKey(SerializedKey.UserId)   as? Int    ?? 0
        self.uuid     = aDecoder.decodeObjectForKey(SerializedKey.Uuid)     as? String ?? ""
        self.nickName = aDecoder.decodeObjectForKey(SerializedKey.NickName) as? String
    }
    
    func encodeWithCoder(aCoder: NSCoder) {
        
        aCoder.encodeObject(self.userId,   forKey: SerializedKey.UserId)
        aCoder.encodeObject(self.uuid,     forKey: SerializedKey.Uuid)
        aCoder.encodeObject(self.nickName, forKey: SerializedKey.NickName)
    }
}

class UserService {
    
    static let sharedInstance = UserService()
    
    private let userDefaults = NSUserDefaults.standardUserDefaults()
    
    func register(userId userId: Int, uuid: String, nickName: String? = nil) {
        
        let archivedObject = NSKeyedArchiver.archivedDataWithRootObject(User(userId: userId, uuid: uuid, nickName: nickName))
        self.userDefaults.setObject(archivedObject, forKey: UserDefaultsKey.User)
        self.userDefaults.synchronize()
    }

    var registeredUser: User? {
        
        guard let unarchivedObject = self.userDefaults.objectForKey(UserDefaultsKey.User) as? NSData,
            let user = NSKeyedUnarchiver.unarchiveObjectWithData(unarchivedObject) as? User else {

            return nil
        }
        
        return user
    }
}

使用時

// 保存
UserService.sharedInstance.register(userId: 1, uuid: "xxxxx")

// 取得
let user = UserService.sharedInstance.registeredUser

この方法でNSDataにすればシリアライズ・デシリアライズできるのでNSUserDefaultsではなくファイルとしても保存できる。

参考:

iOS でオブジェクトをシリアライズしてファイルに保存する方法 - A Day In The Life
http://glassonion.hatenablog.com/entry/20110904/1315145330