나는이 오류의 원인을 알고 있다고 생각했지만 내가 뭘 잘못했는지 알 수없는 것 같습니다.
내가받는 전체 오류 메시지는 다음과 같습니다.
속성 목록이 아닌 개체를 설정하려고합니다 ( "<BC_Person : 0x8f3c140>" )를 키 personDataArray에 대한 NSUserDefaults 값으로
나는이 Person
난에 부합되는 생각 클래스 NSCoding
내 사람 클래스에서 이러한 방법 모두이 프로토콜을 :
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.personsName forKey:@"BCPersonsName"];
[coder encodeObject:self.personsBills forKey:@"BCPersonsBillsArray"];
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
self.personsName = [coder decodeObjectForKey:@"BCPersonsName"];
self.personsBills = [coder decodeObjectForKey:@"BCPersonsBillsArray"];
}
return self;
}
응용 프로그램의 어떤 시점에서, NSString
에서이 BC_PersonClass
설정하고, 나는이되어 DataSave
나는 내에서 속성을 인코딩 처리하는 생각 클래스를 BC_PersonClass
. DataSave
클래스 에서 사용중인 코드는 다음과 같습니다 .
- (void)savePersonArrayData:(BC_Person *)personObject
{
// NSLog(@"name of the person %@", personObject.personsName);
[mutableDataArray addObject:personObject];
// set the temp array to the mutableData array
tempMuteArray = [NSMutableArray arrayWithArray:mutableDataArray];
// save the person object as nsData
NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];
// first add the person object to the mutable array
[tempMuteArray addObject:personEncodedObject];
// NSLog(@"Objects in the array %lu", (unsigned long)mutableDataArray.count);
// now we set that data array to the mutable array for saving
dataArray = [[NSArray alloc] initWithArray:mutableDataArray];
//dataArray = [NSArray arrayWithArray:mutableDataArray];
// save the object to NS User Defaults
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:dataArray forKey:@"personDataArray"];
[userData synchronize];
}
이것이 내가하려는 일에 대한 아이디어를 줄 수있는 충분한 코드이기를 바랍니다. 다시 한 번 BC_Person 클래스에서 내 속성을 인코딩하는 방법에 문제가 있다는 것을 알고 있습니다. 내가 잘못하고있는 것을 파악할 수는 없습니다.
도와 주셔서 감사합니다!
답변
게시 한 코드는에 맞춤 객체 배열을 저장하려고합니다 NSUserDefaults
. 당신은 그렇게 할 수 없습니다. 구현하는 NSCoding
방법은 도움이되지 않습니다. 당신은 같은 것들을 저장할 수있다 NSArray
, NSDictionary
, NSString
, NSData
, NSNumber
,과 NSDate
에서를 NSUserDefaults
.
당신은에 개체를 변환 할 필요가 NSData
있음을 (당신이 코드의 일부가 같은) 저장 NSData
에서 NSUserDefaults
. 당신은 심지어 저장할 수 NSArray
의 NSData
당신이 필요로하는 경우입니다.
배열을 읽을 때 객체를 NSData
되 찾으 려면를 보관 해제 해야 BC_Person
합니다.
아마도 당신은 이것을 원할 것입니다 :
- (void)savePersonArrayData:(BC_Person *)personObject {
[mutableDataArray addObject:personObject];
NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:mutableDataArray.count];
for (BC_Person *personObject in mutableDataArray) {
NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];
[archiveArray addObject:personEncodedObject];
}
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:archiveArray forKey:@"personDataArray"];
}
답변
배열을 통해 객체를 NSData로 직접 인코딩하는 것은 다소 낭비 적입니다. 귀하의 오류 BC_Person is a non-property-list object
는 프레임 워크가 person 객체를 직렬화하는 방법을 모른다는 것을 알려줍니다.
따라서 개인 개체가 NSCoding을 준수하도록하려면 사용자 지정 개체 배열을 NSData로 변환하고 기본값으로 저장할 수 있습니다. 놀이터 :
편집 : NSUserDefaults
Xcode 7에서 쓰기 가 중단되어 놀이터에서 데이터를 보관하고 출력을 다시 인쇄합니다. UserDefaults 단계는 나중에 고정 될 경우에 포함됩니다.
//: Playground - noun: a place where people can play
import Foundation
class Person: NSObject, NSCoding {
let surname: String
let firstname: String
required init(firstname:String, surname:String) {
self.firstname = firstname
self.surname = surname
super.init()
}
//MARK: - NSCoding -
required init(coder aDecoder: NSCoder) {
surname = aDecoder.decodeObjectForKey("surname") as! String
firstname = aDecoder.decodeObjectForKey("firstname") as! String
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(firstname, forKey: "firstname")
aCoder.encodeObject(surname, forKey: "surname")
}
}
//: ### Now lets define a function to convert our array to NSData
func archivePeople(people:[Person]) -> NSData {
let archivedObject = NSKeyedArchiver.archivedDataWithRootObject(people as NSArray)
return archivedObject
}
//: ### Create some people
let people = [Person(firstname: "johnny", surname:"appleseed"),Person(firstname: "peter", surname: "mill")]
//: ### Archive our people to NSData
let peopleData = archivePeople(people)
if let unarchivedPeople = NSKeyedUnarchiver.unarchiveObjectWithData(peopleData) as? [Person] {
for person in unarchivedPeople {
print("\(person.firstname), you have been unarchived")
}
} else {
print("Failed to unarchive people")
}
//: ### Lets try use NSUserDefaults
let UserDefaultsPeopleKey = "peoplekey"
func savePeople(people:[Person]) {
let archivedObject = archivePeople(people)
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(archivedObject, forKey: UserDefaultsPeopleKey)
defaults.synchronize()
}
func retrievePeople() -> [Person]? {
if let unarchivedObject = NSUserDefaults.standardUserDefaults().objectForKey(UserDefaultsPeopleKey) as? NSData {
return NSKeyedUnarchiver.unarchiveObjectWithData(unarchivedObject) as? [Person]
}
return nil
}
if let retrievedPeople = retrievePeople() {
for person in retrievedPeople {
print("\(person.firstname), you have been unarchived")
}
} else {
print("Writing to UserDefaults is still broken in playgrounds")
}
그리고 Voila, NSUserDefaults에 커스텀 객체 배열을 저장했습니다.
답변
저장하려면 :
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:yourObject];
[currentDefaults setObject:data forKey:@"yourKeyName"];
얻는 방법 :
NSData *data = [currentDefaults objectForKey:@"yourKeyName"];
yourObjectType * token = [NSKeyedUnarchiver unarchiveObjectWithData:data];
제거
[currentDefaults removeObjectForKey:@"yourKeyName"];
답변
스위프트 3 솔루션
간단한 유틸리티 클래스
class ArchiveUtil {
private static let PeopleKey = "PeopleKey"
private static func archivePeople(people : [Human]) -> NSData {
return NSKeyedArchiver.archivedData(withRootObject: people as NSArray) as NSData
}
static func loadPeople() -> [Human]? {
if let unarchivedObject = UserDefaults.standard.object(forKey: PeopleKey) as? Data {
return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [Human]
}
return nil
}
static func savePeople(people : [Human]?) {
let archivedObject = archivePeople(people: people!)
UserDefaults.standard.set(archivedObject, forKey: PeopleKey)
UserDefaults.standard.synchronize()
}
}
모델 클래스
class Human: NSObject, NSCoding {
var name:String?
var age:Int?
required init(n:String, a:Int) {
name = n
age = a
}
required init(coder aDecoder: NSCoder) {
name = aDecoder.decodeObject(forKey: "name") as? String
age = aDecoder.decodeInteger(forKey: "age")
}
public func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(age, forKey: "age")
}
}
전화하는 방법
var people = [Human]()
people.append(Human(n: "Sazzad", a: 21))
people.append(Human(n: "Hissain", a: 22))
people.append(Human(n: "Khan", a: 23))
ArchiveUtil.savePeople(people: people)
let others = ArchiveUtil.loadPeople()
for human in others! {
print("name = \(human.name!), age = \(human.age!)")
}
답변
스위프트 -4 Xcode 9.1
이 코드를 사용해보십시오
NSUserDefault에 매퍼를 저장할 수 없으며 NSData, NSString, NSNumber, NSDate, NSArray 또는 NSDictionary 만 저장할 수 있습니다.
let myData = NSKeyedArchiver.archivedData(withRootObject: myJson)
UserDefaults.standard.set(myData, forKey: "userJson")
let recovedUserJsonData = UserDefaults.standard.object(forKey: "userJson")
let recovedUserJson = NSKeyedUnarchiver.unarchiveObject(with: recovedUserJsonData)
답변
우선, rmaddy의 답변 (위)이 옳습니다. 구현 NSCoding
하는 것이 도움이되지 않습니다. 그러나 NSCoding
사용하기 위해 NSKeyedArchiver
모든 것을 구현해야 하므로 한 번만 더 변환하면 via를 통해 변환 할 수 NSData
있습니다.
방법 예
- (NSUserDefaults *) defaults {
return [NSUserDefaults standardUserDefaults];
}
- (void) persistObj:(id)value forKey:(NSString *)key {
[self.defaults setObject:value forKey:key];
[self.defaults synchronize];
}
- (void) persistObjAsData:(id)encodableObject forKey:(NSString *)key {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:encodableObject];
[self persistObj:data forKey:key];
}
- (id) objectFromDataWithKey:(NSString*)key {
NSData *data = [self.defaults objectForKey:key];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
당신은 당신의 포장 수 NSCoding
개체를 NSArray
하거나 NSDictionary
또는 무엇이든 …
답변
이 문제는에 사전을 저장하려고했습니다 NSUserDefaults
. NSNull
값 을 포함했기 때문에 저장하지 않을 것으로 나타났습니다 . 그래서 방금 사전을 변경 가능한 사전에 복사하여 null을 제거한 다음에 저장했습니다.NSUserDefaults
NSMutableDictionary* dictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary_trying_to_save];
[dictionary removeObjectForKey:@"NullKey"];
[[NSUserDefaults standardUserDefaults] setObject:dictionary forKey:@"key"];
이 경우 어떤 키가 NSNull
값 이 될 수 있는지 알았습니다 .