NSCoding + NSKeyed(Un)Archiver
안녕하세요. 오늘은 데이터를 디바이스에 영구적으로 저장하는 방법, 그중에서도 String
, Int
, Float
과 같은 기본 데이터 타입이 아닌 클래스의 인스턴스와 같은 사용자 정의 데이터 타입을 저장하는 방법을 알아보도록 하겠습니다.
이 포스팅을 들어가기 앞서 제가 작성한 UserDefaults
를 활용한 데이터 저장법을 먼저 보고 오시면 포스팅을 읽는데 도움이 되실 것 같습니다.
저는 이번 예제에서 해야 할 일들의 목록인 "ToDo List" 을 기록하는 간단한 어플리케이션을 만들며 진행하도록 하겠습니다. 그럼 바로 시작해보도록 하겠습니다
NSCoding
UserDefaults
를 이용해 바로 저장하던 기본 데이터 타입과는 다르게 사용자 정의 타입의 데이터는 Archive와 Unarchive라는 전처리 과정을 거쳐야 UserDefaults
에 저장이 가능합니다. 이를 위해서는 먼저 저장하려는 사용자 정의 타입은 NSObject
를 상속받고 NSCoding
이라는 프로토콜을 준수해야 합니다.
프로토콜을 준수한다고 명시하였기 때문에 요구되는 메소드들을 구현해주어야 합니다.
encode(with:)
: 이 메소드는 밑에서 다룰 직접적으로 Archive 행위를 하는 NSKeyedArchiver
가 압축을 진행할 때 호출되는 메소드로 압축을 진행하는 모델(사용자 정의 타입)의 프로퍼티들을 압축하는 행위를 합니다.
init(coder:)
: 이 메소드는 역시 밑에서 다룰 Unarchive 행위를 하는 NSKeyedUnarchiver
가 압축된 데이터를 해제하고 해제된 데이터를 ToDo
로 타입 캐스팅을 할 때 호출되는 생성자로 해제된 데이터를 프로퍼티에 할당합니다.
NSKeyed(Un)Archiver
아카이빙을 할 타입이 NSCoding
프로토콜을 준수하고 나면 이젠 실제로 아카이빙을 구현하면 됩니다.
- 먼저
NSKeyedArchiver
를 통해 아카이빙을 합니다. 이때 단순히 withRootObject
로 아카이빙을 할 수 있지만 archiveRootObject(rootObject: toFile:)
와 같이 특정 파일에 저장을 할 수도 있습니다. 그리고 이렇게 반환되는 압축된 데이터의 타입은 Data
타입입니다.
- 압축된
Data
타입의 encodedData
를 UserDefaults
에 저장합니다.
- 데이터를 불러올 때는
UserDefaults
로 값을 불러오고 이를 저장했던 Data
타입으로 타입 검사를 하고 캐스팅을 합니다.
- 그리고 불러온
Data
타입의 압축된 데이터를 NSKeyedUnarchiver
를 통해 압축했던 당시 데이터로 타입 캐스팅을 하여 반환합니다.
이 과정을 위의 NSCoding
과 연관 지어 생각해보면 1번 코드가 실행될 때 내부적으로 NSCoding
의 메소드 중 encode(with:)
이 호출되는 것이고 4번 코드가 실행될 때 init(coder:)
이 호출되는 것입니다.
마무리
오늘은 이렇게 사용자 정의 타입을 저장하기 위해 사용되는 아카이빙과 언아카이빙에 대해 알아보았습니다. 이렇게 NSCoding
과 NSKeyed(Un)Archiver
를 이용하는 것이 편해 보이시나요? 저의 예제에서는 프로퍼티가 두개였지만 만일 더 많은 프로퍼티와 프로퍼티 간의 관계가 복잡한 경우에는 어떻게 해야 할까요? 코드도 굉장히 복잡해질 것입니다.
이를 보완하고자 Swift4에서는 Codable
이라는 새로운 프로토콜이 나왔는데요. 다음 포스팅에서는 이 Codable
에 대해 알아보는 시간을 갖도록 하겠습니다. 감사합니다.
Source : github
참고자료
- Stackoverflow
- NSCoding / NSKeyedArchiver