214

このエラーの原因はわかっていると思っていましたが、何が間違っていたのかわかりません。

これが私が得ている完全なエラーメッセージです:

プロパティリスト以外のオブジェクトを設定しようとしています (
   "<BC_Person: 0x8f3c140>"
) key 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;
}

アプリのある時点で、NSStringBC_PersonClassが設定され、DataSaveのプロパティのエンコードを処理していると思われるクラスがありますBC_PersonClassDataSaveクラスから使用しているコードは次のとおりです。

- (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 クラスで自分のプロパティをエンコードする方法に問題があることを知っていますが、何が間違っているのかわかりません。

助けてくれてありがとう!

4

12 に答える 12

284

投稿したコードは、カスタム オブジェクトの配列を に保存しようとしますNSUserDefaults。そんなことはできません。メソッドの実装はNSCoding役に立ちません。NSArrayNSDictionaryNSStringNSDataNSNumber、およびNSDateのようなもののみを格納できますNSUserDefaults

NSDataオブジェクトを(一部のコードにあるように)に変換し、それをNSDataに保存する必要がありNSUserDefaultsます。NSArray必要に応じてof を保存することもでき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"];
}
于 2013-11-01T04:13:56.177 に答える
67

配列を調べてオブジェクトを自分で NSData にエンコードするのは、私にはかなり無駄に思えます。エラーBC_Person is a non-property-list objectは、フレームワークが person オブジェクトをシリアル化する方法を認識していないことを示しています。

したがって、必要なことは、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")
}

そしてほら、カスタムオブジェクトの配列を NSUserDefaults に保存しました

于 2015-01-29T15:30:18.387 に答える
52

保存する:

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"];
于 2016-02-08T19:04:35.237 に答える
14

Swift-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)
于 2018-05-23T05:47:23.863 に答える
4

Swift 5非常に簡単な方法

//MARK:- First you need to encoded your arr or what ever object you want to save in UserDefaults
//in my case i want to save Picture (NMutableArray) in the User Defaults in
//in this array some objects are UIImage & Strings

//first i have to encoded the NMutableArray 
let encodedData = NSKeyedArchiver.archivedData(withRootObject: yourArrayName)
//MARK:- Array save in UserDefaults
defaults.set(encodedData, forKey: "YourKeyName")

//MARK:- When you want to retreive data from UserDefaults
let decoded  = defaults.object(forKey: "YourKeyName") as! Data
yourArrayName = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! NSMutableArray

//MARK: Enjoy this arrry "yourArrayName"
于 2019-06-17T06:14:23.553 に答える