カスタムクラスをUserDefaultに保存・取得する方法


環境

xcode 10.3
Objective-C 2.0
Swift 5.0.3

Objective-Cでの方法

CustomClass.h
#import <Foundation/Foundation.h>

@interface CustomClass : NSObject <NSCoding, NSSecureCoding> {
    // 番号
    NSInteger identify;
    // 名前
    NSString* name;
}
// イニシャライザ
- (instancetype)init: (NSInteger)identify name:(NSString*)name;
@end
CustomClass.m
#import "CustomClass.h"

@implementation CustomClass

/**
 イニシャライザ

 @param identify 番号
 @param name 名前
 @return インスタンス
 */
- (instancetype)init: (NSInteger)identify name:(NSString*)name {
    if (self = [super init]) {
        self->identify = identify;
        self->name = name;
    }
    return self;
}

/**
 デコーダーからイニシャライズする

 @param aDecoder デコーダー
 @return インスタンス
 */
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {

    if (self = [super init]) {
        identify = [aDecoder decodeIntegerForKey:@"identify"];
        name = [aDecoder decodeObjectForKey:@"name"];
    }
    return self;
}

/**
 エンコード

 @param aCoder コーダー
 */
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
    [aCoder encodeInteger:identify forKey:@"identify"];
    [aCoder encodeObject:name forKey:@"name"];
}

/**
 セキュアコーディングを有効にする

 @return YES = 有効
 */
+ (BOOL)supportsSecureCoding
{
    return YES;
}

@end
ViewController.m
#import "ViewController.h"
#import "CustomClass.h"

@interface ViewController ()

@end

@implementation ViewController

#pragma mark - ********** イニシャライザ **********

/**
 画面ロードが完了した際に呼ばれます
 */
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    CustomClass* test = [[CustomClass alloc] init:0 name:@"name"];
    NSData* data = [NSKeyedArchiver archivedDataWithRootObject:test requiringSecureCoding:false error:nil];
    [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"test"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    NSData* getData = [[NSUserDefaults standardUserDefaults] dataForKey:@"test"];
    CustomClass* getTest = (CustomClass*)[NSKeyedUnarchiver CustomClass.class fromData:getData error:nil];
    NSLog(@"%@", getTest);
}

@end

Swiftでの方法

CustomClass.swift
import Foundation

class CustomClass: NSObject, NSCoding {

    /// 番号
    var id = 0
    /// 名前
    var name = ""

    /// イニシャライザ
    ///
    /// - Parameters:
    ///   - id: 番号
    ///   - name: 名前
    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }

    /// デコーダーからイニシャライズ
    ///
    /// - Parameter aDecoder: デコーダー
    required init?(coder aDecoder: NSCoder) {
        id = aDecoder.decodeObject(forKey: "id") as? Int ?? 0
        name = aDecoder.decodeObject(forKey: "name") as? String ?? ""
    }

    /// エンコード
    ///
    /// - Parameter aCoder: コーダー
    func encode(with aCoder: NSCoder) {
        aCoder.encode(id, forKey: "id")
        aCoder.encode(name, forKey: "name")
    }
}
ViewController.swift
import UIKit

class ViewController: UIViewController {

    // MARK: - ********** イニシャライザ **********

    /// 画面ロードが完了した際に呼ばれます
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let test = CustomClass(id: 0, name: "name")
        do {
            let _test = try? NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: false)
            UserDefaults.standard.set(_test, forKey: "test")
        }

        let getData = UserDefaults.standard.data(forKey: "test")!
        do {
            guard let tmpTest = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(getData) as? CustomClass else {
                return;
            }
            print(tmpTest)
        }
    }
}