LoginSignup
25
20

More than 3 years have passed since last update.

[iOS] カスタムクラスをData型に変換する(UserDefaultsにカスタムクラスの配列を保存する)

Last updated at Posted at 2018-05-07

(コメントにて@ObuchiYukiさんのご指摘にもありますが、)
本記事の内容は古く、現在であればCodableを使用するのが簡単に思います。

下記に例を示します。

保存対象のカスタムクラス

struct Item: Codable {
    let id: Int
    let name: String
}

保存処理

func saveItems(items: [Item]) {
    let data = items.map { try! JSONEncoder().encode($0) }
    userDefaults.set(data as [Any], forKey: "キー名")
}

読み取り処理


func readItems() -> [Item]? {
    guard let items = userDefaults.array(forKey: "キー名") as? [Data] else { return [Item]() }

    let decodedItems = items.map { try! JSONDecoder().decode(Item.self, from: $0) }
    return decodedItems
}

カスタムクラスをData型に変換する必要性

例えばUserDefaultsを使用する場合、カスタムオブジェクトをNSDataに変換する必要があります :)

なぜかというと、UserDefaultsで保存できる型は NSData, NSString, NSNumber, NSDate, NSArray, NSDictionary となっているからです。

これ以外の型を保持させたい場合は一旦NSData型に変換してから保持し、読み込む際はNSData型として読み込んだ後に型変換を行う必要があります。

以下では「UserDefaultsにてカスタムクラスの配列を保存、読み込む」という具体的なケースで、Swift4でカスタムクラスをData型に変換する処理を見ていきます😄

流れ

iOS ではシリアライズすることをアーカイブ、デシリアライズすることをアンアーカイブといいます。
アーカイブのためのクラスとして NSKeyedArchiver クラス
アンアーカイブのためのクラスとして NSKeyedUnarchiver クラスがあります。

概要図 2018-05-04 13.26.58.png

UserDefaultsにカスタムクラスの配列を保存・読み込みをする

まず、独自に作成するカスタムクラスを定義します。

<ポイント>
NSObject, NSCodingを継承する
エンコード、デコード処理を記述する

class SomeObj: NSObject, NSCoding {

    var word: String!
    var date: String!

    init(word: String, date: String) {
        self.word = word
        self.date = date
    }

    required init?(coder aDecoder: NSCoder) {
        self.word = aDecoder.decodeObject(forKey: "word") as! String
        self.date = aDecoder.decodeObject(forKey: "date") as! String
    }

    func encode(with aCoder: NSCoder) {
        if let word = word { aCoder.encode(word, forKey: "word") }
        if let date = date { aCoder.encode(date, forKey: "date") }
    }
}

保存処理ではNSKeyedArchiver.archivedDataを使用します


var someObjArray = [SomeObj]()
let someObj = SomeObj(word: "hoge", date: "2000/01/01")

someObjArray.insert(someObj, at: 0) 

UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: someObjArray), forKey: "someObjs")

読み込み処理では、一度Data型で読み込んだものをNSKeyedUnarchiver.unarchiveObjecを使用してアンアーカイブ(デシリアライズ)します


func loadSomeObjs() -> [someObj]?{
        if let loadedData = UserDefaults().data(forKey: "someObjs") {
            let someObjs = NSKeyedUnarchiver.unarchiveObject(with: loadedData) as! [SomeObj]
            return someObjs
        }else {
            return nil
        }
}

これでUserDefaultsにカスタムクラスの配列を保存したり、読み込んだりできるようになります!

25
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
20