Baiklah, jadi saya telah melakukan beberapa pencarian, dan saya menyadari masalah saya, tetapi saya tidak tahu bagaimana cara memperbaikinya. Saya telah membuat kelas khusus untuk menampung beberapa data. Saya membuat objek untuk kelas ini, dan saya perlu mereka untuk bertahan di antara sesi. Sebelum saya memasukkan semua informasi saya NSUserDefaults
, tetapi ini tidak berfungsi.
-[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '<Player: 0x3b0cc90>' of class 'Player'.
Itu adalah pesan kesalahan yang saya dapatkan ketika saya menempatkan kelas kustom saya, "Player", di menu NSUserDefaults
. Sekarang, saya sudah membaca yang ternyata NSUserDefaults
hanya menyimpan beberapa jenis informasi. Jadi bagaimana saya mendapatkan objek saya NSUSerDefaults
?
Saya membaca bahwa harus ada cara untuk "menyandikan" objek kustom saya dan kemudian memasukkannya, tetapi saya tidak yakin bagaimana cara mengimplementasikannya, bantuan akan dihargai! Terima kasih!
**** EDIT ****
Baiklah, jadi saya bekerja dengan kode yang diberikan di bawah ini (Terima kasih!), Tapi saya masih mengalami beberapa masalah. Pada dasarnya, kode mogok sekarang dan saya tidak yakin mengapa, karena tidak memberikan kesalahan. Mungkin aku melewatkan sesuatu yang mendasar dan aku terlalu lelah, tapi kita akan lihat. Ini adalah implementasi kelas Custom saya, "Player":
@interface Player : NSObject {
NSString *name;
NSNumber *life;
//Log of player's life
}
//Getting functions, return the info
- (NSString *)name;
- (int)life;
- (id)init;
//These are the setters
- (void)setName:(NSString *)input; //string
- (void)setLife:(NSNumber *)input; //number
@end
File Implementasi:
#import "Player.h"
@implementation Player
- (id)init {
if (self = [super init]) {
[self setName:@"Player Name"];
[self setLife:[NSNumber numberWithInt:20]];
[self setPsnCounters:[NSNumber numberWithInt:0]];
}
return self;
}
- (NSString *)name {return name;}
- (int)life {return [life intValue];}
- (void)setName:(NSString *)input {
[input retain];
if (name != nil) {
[name release];
}
name = input;
}
- (void)setLife:(NSNumber *)input {
[input retain];
if (life != nil) {
[life release];
}
life = input;
}
/* This code has been added to support encoding and decoding my objecst */
-(void)encodeWithCoder:(NSCoder *)encoder
{
//Encode the properties of the object
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeObject:self.life forKey:@"life"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if ( self != nil )
{
//decode the properties
self.name = [decoder decodeObjectForKey:@"name"];
self.life = [decoder decodeObjectForKey:@"life"];
}
return self;
}
-(void)dealloc {
[name release];
[life release];
[super dealloc];
}
@end
Jadi itu kelas saya, cukup lurus ke depan, saya tahu itu berfungsi dalam membuat objek saya. Jadi di sini adalah bagian yang relevan dari file AppDelegate (tempat saya memanggil fungsi enkripsi dan dekripsi):
@class MainViewController;
@interface MagicApp201AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MainViewController *mainViewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) MainViewController *mainViewController;
-(void)saveCustomObject:(Player *)obj;
-(Player *)loadCustomObjectWithKey:(NSString*)key;
@end
Dan kemudian bagian penting dari file implementasi:
#import "MagicApp201AppDelegate.h"
#import "MainViewController.h"
#import "Player.h"
@implementation MagicApp201AppDelegate
@synthesize window;
@synthesize mainViewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
//First check to see if some things exist
int startup = [prefs integerForKey:@"appHasLaunched"];
if (startup == nil) {
//Make the single player
Player *singlePlayer = [[Player alloc] init];
NSLog([[NSString alloc] initWithFormat:@"%@\n%d\n%d",[singlePlayer name], [singlePlayer life], [singlePlayer psnCounters]]); // test
//Encode the single player so it can be stored in UserDefaults
id test = [MagicApp201AppDelegate new];
[test saveCustomObject:singlePlayer];
[test release];
}
[prefs synchronize];
}
-(void)saveCustomObject:(Player *)object
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
[prefs setObject:myEncodedObject forKey:@"testing"];
}
-(Player *)loadCustomObjectWithKey:(NSString*)key
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData *myEncodedObject = [prefs objectForKey:key ];
Player *obj = (Player *)[NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
return obj;
}
Eeee, maaf tentang semua kode. Hanya berusaha membantu. Pada dasarnya, aplikasi akan diluncurkan dan kemudian crash dengan segera. Saya mempersempitnya ke bagian enkripsi aplikasi, di situlah crash, jadi saya melakukan sesuatu yang salah tetapi saya tidak yakin apa. Bantuan akan dihargai kembali, terima kasih!
(Saya belum sempat mendekripsi, karena saya belum mengenkripsi bekerja.)
sumber
Jawaban:
Pada kelas Player Anda, terapkan dua metode berikut (mengganti panggilan ke encodeObject dengan sesuatu yang relevan dengan objek Anda sendiri):
Membaca dan menulis dari
NSUserDefaults
:Kode dipinjam tanpa malu dari: saving class in nsuserdefaults
sumber
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
untukNSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
. Variabel tidak cocok.Saya membuat perpustakaan RMMapper ( https://github.com/roomorama/RMMapper ) untuk membantu menyimpan objek khusus ke NSUserDefaults lebih mudah dan nyaman, karena menerapkan encodeWithCoder dan initWithCoder sangat membosankan!
Untuk menandai kelas sebagai arsip, cukup gunakan:
#import "NSObject+RMArchivable.h"
Untuk menyimpan objek khusus ke NSUserDefaults:
Untuk mendapatkan objek khusus dari NSUserDefaults:
sumber
Cepat 4
Memperkenalkan protokol Codable yang melakukan semua keajaiban untuk tugas-tugas semacam ini. Cukup sesuaikan struct / kelas khusus Anda dengan itu:
Dan untuk menyimpan di Default Anda dapat menggunakan PropertyListEncoder / Decoder :
Ini akan berfungsi seperti itu untuk array dan kelas-kelas kontainer lain dari objek-objek seperti itu juga:
sumber
Codable
perilaku secara gratis ketika semua anggota contoh adalah diri mereka sendiriCodable
- jika tidak, Anda harus menulis sendiri beberapa kode penyandian,Codable
juga. Dan seterusnya, secara rekursif. Hanya dalam kasus yang sangat khusus Anda perlu menulis kode penyandian.Jika ada yang mencari versi cepat:
1) Buat kelas khusus untuk data Anda
2) Untuk menyimpan data, gunakan fungsi berikut:
3) Untuk mengambil:
Catatan: Di sini saya menyimpan dan mengambil larik objek kelas kustom.
sumber
Mengambil jawaban @ chrissr dan menjalankannya, kode ini dapat diimplementasikan ke dalam kategori yang bagus
NSUserDefaults
untuk menyimpan dan mengambil objek khusus:Pemakaian:
sumber
Cepat 3
untuk menyimpan dan mengambil:
sumber
self
tidak wajib sebelum variabel dalaminit
danencode
.Sinkronisasi data / objek yang telah Anda simpan ke dalam NSUserDefaults
Semoga ini bisa membantu Anda. Terima kasih
sumber