iOS12 unarchiveObject(with:) was deprecated に対応する

# はじめに
swiftで自身で定義したクラスをUserDefaultsに保存&ロードすることがよくありますが，iOS12では

* archivedData(withRootObject:)
* unarchiveObject(with:)

が非推奨になりました．書き換えに手間取ったので手順を記録しておきます．

## 確認環境
Xcode Version 10.1
Swift 4.2.1
iOS 12.0

# 変更前
```swift:変更前.swift
// 保存したいクラス
class MyClass: NSObject, NSCoding{
    var dataValue:String

    init(value: String){
        self.dataValue = value
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(dataValue, forKey: "dataKey")
    }
    
    required init?(coder aDecoder: NSCoder) {
        self.dataValue = (aDecoder.decodeObject(forKey: "dataKey") as! String)
    }
}

// 保存処理
func saveData(_ value : MyClass){
    let archiveData = NSKeyedArchiver.archivedData(withRootObject: value)
    UserDefaults.standard.set(archiveData, forKey: "key")
}

// ロード処理
func loadData() -> MyClass?{
    if let loadedData = UserDefaults().data(forKey: "key") {
        return  NSKeyedUnarchiver.unarchiveObject(with: loadedData) as! MyClass
    }
    return nil
}


// データを作成してUserDefaultsに保存
let myClass = MyClass(value: "保存データ")
saveData(myClass)

// UserDefaultsからデータを取得
let loadClass = loadData()

print(loadClass!.dataValue) // "保存データ"
```

この状態だとiOS12では以下の警告が表示されます．

* 'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead
* 'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead

# 変更後
上記のコードを警告が出ないように書き換えると以下のようになります．
※ 変更点はコメントに記載しています．

```swift:変更後
// 保存したいクラス
class MyClass: NSObject, NSSecureCoding{ // ⭐️NSCoding→NSSecureCodingに変更
    static var supportsSecureCoding: Bool = true // ⭐️NSSecureCodingのprotocolに定義されているため追加
    
    var dataValue:String
    
    init(value: String){
        self.dataValue = value
    }
    
    func encode(with aCoder: NSCoder) {
        aCoder.encode(dataValue, forKey: "dataKey")
    }
    
    required init?(coder aDecoder: NSCoder) {
        self.dataValue = (aDecoder.decodeObject(forKey: "dataKey") as! String)
    }
}

// 保存処理
func saveData(_ value : MyClass){
    // ⭐️警告で使えと言われたメソッドに変更　例外を投げるのでtry?を追加
    guard let archiveData = try? NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true) else {
        fatalError("Archive failed")
    }
    
    UserDefaults.standard.set(archiveData, forKey: "key")
}

// ロード処理
func loadData() -> MyClass?{
    if let loadedData = UserDefaults().data(forKey: "key") {
        // ⭐️unarchiveTopLevelObjectWithDataに変更　例外を投げるのでtry?を追加
        return try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(loadedData) as! MyClass

        // ⭐️警告で使えと言われたメソッドの場合
        // return try! NSKeyedUnarchiver.unarchivedObject(ofClass: MyClass.self, from:loadedData)
        // ⭐️MyClass内でDateや配列を使っている場合はofClassではなく，ofClassesを利用する
        // return try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [MyClass.self, NSArray.self], from: loadedData) as! MyClass
        
    }
    return nil
}

// データを作成してUserDefaultsに保存
let myClass = MyClass(value: "保存データ")
saveData(myClass)

// UserDefaultsからデータを取得
let loadClass = loadData()

print(loadClass!.dataValue) // "保存データ"
```

## 補足
unarchiveObjectの警告で使えと言われている
`NSKeyedUnarchiver.unarchivedObject(ofClasses: [MyClass.self], from: loadedData)`
を利用しても良いのですが，MyClassの中で日付や配列などを利用していると，利用クラスを列挙するため
`NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, MyClass.self, NSDate.self, NSDictionary.self], from: loadedData)`
のように長くなるので，NSxxx.selfを含むunarchiveTopLevelObjectWithDataの利用がオススメです．

## リファレンス
[Foundation Release Notes](https://developer.apple.com/documentation/ios_release_notes/ios_12_release_notes/foundation_release_notes)