userDefaults에서 사용자 지정 개체 저장 및 검색 Swift 3
Swift 3, Xcode 8.0을 사용하여 Playground에 있습니다.
import Foundation
class Person: NSObject, NSCoding {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required convenience init(coder aDecoder: NSCoder) {
let name = aDecoder.decodeObject(forKey: "name") as! String
let age = aDecoder.decodeObject(forKey: "age") as! Int
self.init(
name: name,
age: age
)
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(age, forKey: "age")
}
}
Person 배열 생성
let newPerson = Person(name: "Joe", age: 10)
var people = [Person]()
people.append(newPerson)
배열 인코딩
let encodedData = NSKeyedArchiver.archivedData(withRootObject: people)
print("encodedData: \(encodedData))")
userDefaults에 저장
let userDefaults: UserDefaults = UserDefaults.standard()
userDefaults.set(encodedData, forKey: "people")
userDefaults.synchronize()
검사
print("saved object: \(userDefaults.object(forKey: "people"))")
userDefaults에서 검색
if let data = userDefaults.object(forKey: "people") {
let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: data as! Data)
print("myPeopleList: \(myPeopleList)")
}else{
print("There is an issue")
}
보관 된 데이터 만 확인
if let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: encodedData){
print("myPeopleList: \(myPeopleList)")
}else{
print("There is an issue")
}
userDefaults에 데이터 개체를 올바르게 저장할 수 없으며 하단의 검사에서 "치명적 오류 : 선택 값을 풀 때 예기치 않게 nil을 찾았습니다"라는 오류가 발생합니다. "check"행은 또한 저장된 객체가 nil임을 보여줍니다. 내 개체의 NSCoder에 오류가 있습니까?
스위프트 4 노트
플레이 그라운드에서 값을 다시 저장 / 테스트 할 수 있습니다.
스위프트 3
UserDefaults는 실제 프로젝트에서 테스트해야합니다. 참고 : 강제로 동기화 할 필요가 없습니다. 플레이 그라운드에서 코딩 / 디코딩을 테스트하려면 keyed archiver를 사용하여 문서 디렉토리의 plist 파일에 데이터를 저장할 수 있습니다. 또한 수업에서 몇 가지 문제를 해결해야합니다.
class Person: NSObject, NSCoding {
let name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.age = decoder.decodeInteger(forKey: "age")
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(age, forKey: "age")
}
}
테스트 :
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// setting a value for a key
let newPerson = Person(name: "Joe", age: 10)
var people = [Person]()
people.append(newPerson)
let encodedData = NSKeyedArchiver.archivedData(withRootObject: people)
UserDefaults.standard.set(encodedData, forKey: "people")
// retrieving a value for a key
if let data = UserDefaults.standard.data(forKey: "people"),
let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Person] {
myPeopleList.forEach({print( $0.name, $0.age)}) // Joe 10
} else {
print("There is an issue")
}
}
}
let age = aDecoder.decodeObject(forKey: "age") as! Int
이것은 Swift 3에서 변경되었습니다. 더 이상 값 유형에 대해 작동하지 않습니다. 이제 올바른 구문은 다음과 같습니다.
let age = aDecoder.decodeInteger(forKey: "age")
다양한 유형에 대한 관련 decode ... () 함수가 있습니다.
let myBool = aDecoder.decodeBoolean(forKey: "myStoredBool")
let myFloat = aDecoder.decodeFloat(forKey: "myStoredFloat")
편집 : Swift 3에서 가능한 모든 decodeXXX 기능의 전체 목록
편집하다:
Another important note: If you have previously saved data that was encoded with an older version of Swift, those values must be decoded using decodeObject(), however once you re-encode the data using encode(...) it can no longer be decoded with decodeObject() if it's a value type. Therefore Markus Wyss's answer will allow you to handle the case where the data was encoded using either Swift version:
self.age = aDecoder.decodeObject(forKey: "age") as? Int ?? aDecoder.decodeInteger(forKey: "age")
Try this:
self.age = aDecoder.decodeObject(forKey: "age") as? Int ?? aDecoder.decodeInteger(forKey: "age")
In Swift 4:
You can use Codable to save and retrieve custom object from the Userdefaults. If you're doing it frequently then you can add as extension and use it like below.
extension UserDefaults {
func save<T:Encodable>(customObject object: T, inKey key: String) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(object) {
self.set(encoded, forKey: key)
}
}
func retrieve<T:Decodable>(object type:T.Type, fromKey key: String) -> T? {
if let data = self.data(forKey: key) {
let decoder = JSONDecoder()
if let object = try? decoder.decode(type, from: data) {
return object
}else {
print("Couldnt decode object")
return nil
}
}else {
print("Couldnt find key")
return nil
}
}
}
Your Class must follow Codable. Its just a typealias for both Encodable & Decodable Protocol.
class UpdateProfile: Codable {
//Your stuffs
}
Usage:
let updateProfile = UpdateProfile()
//To save the object
UserDefaults.standard.save(customObject: updateProfile, inKey: "YourKey")
//To retrieve the saved object
let obj = UserDefaults.standard.retrieve(object: UpdateProfile.self, fromKey: "YourKey")
For more Encoding and Decoding Custom types, Please go through the Apple's documentation.
'IT Share you' 카테고리의 다른 글
Ruby 정규식을 여러 줄로 분할 (0) | 2020.11.29 |
---|---|
파이썬에서 어떻게 'git pull'을 호출 할 수 있습니까? (0) | 2020.11.29 |
C 전처리기를 사용하여 파일이 있는지 확인할 수 있습니까? (0) | 2020.11.29 |
System.InvalidOperationException : 임시 클래스를 생성 할 수 없습니다 (result = 1). (0) | 2020.11.29 |
Haskell에서 정수 리터럴을 바이너리 또는 16 진수로 인쇄하는 방법은 무엇입니까? (0) | 2020.11.29 |