Я думал, что я знал, что был причиной этой ошибки, но я могу'т, кажется, чтобы выяснить, что я сделал неправильно.
Вот полное сообщение об ошибке я получаю:
в <предварительно> Попытка установить неимущественные-список объектов ( " и&АМП;ЛТ;BC_Person: 0x8f3c140&ГТ;"и ) как NSUserDefaults значение для ключа personDataArray </пред>
У меня есть человек
класс, я думаю, соответствует `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 ваши ошибки-это не собственность-список объектов` говорит вам, что рамки не'т знаю, как сериализовать свой объект 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
Сохранить:
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!)")
}
попробуйте этот код
вы не можете хранить картографа в 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 и все такое, так он's просто еще один шаг... преобразования с помощью формат 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
значения. Так я просто скопировал из словаря в словарь Мутабельный убрали нули затем сохраняется в NSUserDefaults
NSMutableDictionary* dictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary_trying_to_save];
[dictionary removeObjectForKey:@"NullKey"];
[[NSUserDefaults standardUserDefaults] setObject:dictionary forKey:@"key"];
В этом случае я знал, какие ключи могут быть NSNull ценности.
объект по умолчанию должен быть список—это свойство, экземпляр (или для коллекций, сочетание экземпляров): формат NSData, NSString, NSNumber, NSDate, списка NSArray или NSDictionary.
если вы хотите сохранить любой другой тип объекта, вы должны, как правило, архивировать его для создания экземпляра формат NSData. Дополнительные сведения см. В разделе Настройки и параметры руководство по программированию.
Свифт 5: в Кодируемую протокол может быть использован вместо NSKeyedArchiever.
struct User: Codable {
let id: String
let mail: String
let fullName: String
}
В прив структура настраиваемую оболочку вокруг UserDefaults стандартный объект.
struct Pref {
static let keyUser = "Pref.User"
static var user: User? {
get {
if let data = UserDefaults.standard.object(forKey: keyUser) as? Data {
do {
return try JSONDecoder().decode(User.self, from: data)
} catch {
print("Error while decoding user data")
}
}
return nil
}
set {
if let newValue = newValue {
do {
let data = try JSONEncoder().encode(newValue)
UserDefaults.standard.set(data, forKey: keyUser)
} catch {
print("Error while encoding user data")
}
} else {
UserDefaults.standard.removeObject(forKey: keyUser)
}
}
}
}
Так что вы можете использовать это так:
Pref.user?.name = "John"
if let user = Pref.user {...
Свифт 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"