但是并不是所有的东西都能往里放的,NSUserDefaults只支持NSString,NSNumber,NSDate,NSArray,NSDictionary.NSUserDefaults可以存取一些短小的信息。
如果把一个自定义的类存到一个NSArray里,然后再存到NSUserDefaults里也是不能成功的。
那怎么办呢?
我找到的方法是,让这个自定义类实现<NSCoding>协议中的- (id) initWithCoder: (NSCoder *)coder方法和- (void) encodeWithCoder: (NSCoder *)coder方法(obj-c的协议protocol就是java的接口interface,就是C++的纯虚函数),然后把该自定义的类对象编码到 NSData中,然后可以保存在NSUserDefaults或文件里,然后可以从NSUserDefaults中或文件进行读取。通过NSCoding能实现像JAVA一样能够实现对象的序列化,可以保存对象到文件里。
写了个小demo验证了下。
直接上demo吧。
UserEntity
//
// UserEntity.m
// NSCodingDemo
//
// Created by on 11-5-20.
// Copyright 2011 , Inc. All rights reserved.
//
#import " UserEntity.h "
#import " AddressEntity.h "
#define SAMPLEDATA_KEY_USERNAME (@"userName")
#define SAMPLEDATA_KEY_GENDER (@"gender")
#define SAMPLEDATA_KEY_AGE (@"age")
#define k_FRIENDS (@"frinds")
#define k_ADDRESS (@"address")
#define k_userEntity_addresses (@"addresses")
@implementation UserEntity
@synthesize userName = _userName;
@synthesize gender = _gender;
@synthesize age = _age;
@synthesize friends = _friends;
@synthesize address = _address;
@synthesize addresses = _addresses;
- ( void )dealloc
{
[self.userName release];
[self.friends release];
[self.address release];
[self.addresses release];
[super dealloc];
}
- ( void )encodeWithCoder:(NSCoder * )coder
{
[coder encodeObject:self.userName forKey:SAMPLEDATA_KEY_USERNAME];
[coder encodeInt:self.age forKey:SAMPLEDATA_KEY_AGE];
[coder encodeBool:self.gender forKey:SAMPLEDATA_KEY_GENDER];
[coder encodeObject:self.friends forKey:k_FRIENDS];
[coder encodeObject:self.address forKey:k_ADDRESS];
[coder encodeObject:self.addresses forKey:k_userEntity_addresses];
}
- (id)initWithCoder:(NSCoder * )decoder
{
if (self = [super init])
{
if (decoder == nil)
{
return self;
}
self.userName = [decoder decodeObjectForKey:SAMPLEDATA_KEY_USERNAME];
self.gender = [decoder decodeBoolForKey:SAMPLEDATA_KEY_GENDER];
self.age = [decoder decodeIntForKey:SAMPLEDATA_KEY_AGE];
self.friends = [decoder decodeObjectForKey:k_FRIENDS];
self.address = [decoder decodeObjectForKey:k_ADDRESS];
self.addresses = [decoder decodeObjectForKey: k_userEntity_addresses];
}
return self;
}
@end
// UserEntity.m
// NSCodingDemo
//
// Created by on 11-5-20.
// Copyright 2011 , Inc. All rights reserved.
//
#import " UserEntity.h "
#import " AddressEntity.h "
#define SAMPLEDATA_KEY_USERNAME (@"userName")
#define SAMPLEDATA_KEY_GENDER (@"gender")
#define SAMPLEDATA_KEY_AGE (@"age")
#define k_FRIENDS (@"frinds")
#define k_ADDRESS (@"address")
#define k_userEntity_addresses (@"addresses")
@implementation UserEntity
@synthesize userName = _userName;
@synthesize gender = _gender;
@synthesize age = _age;
@synthesize friends = _friends;
@synthesize address = _address;
@synthesize addresses = _addresses;
- ( void )dealloc
{
[self.userName release];
[self.friends release];
[self.address release];
[self.addresses release];
[super dealloc];
}
- ( void )encodeWithCoder:(NSCoder * )coder
{
[coder encodeObject:self.userName forKey:SAMPLEDATA_KEY_USERNAME];
[coder encodeInt:self.age forKey:SAMPLEDATA_KEY_AGE];
[coder encodeBool:self.gender forKey:SAMPLEDATA_KEY_GENDER];
[coder encodeObject:self.friends forKey:k_FRIENDS];
[coder encodeObject:self.address forKey:k_ADDRESS];
[coder encodeObject:self.addresses forKey:k_userEntity_addresses];
}
- (id)initWithCoder:(NSCoder * )decoder
{
if (self = [super init])
{
if (decoder == nil)
{
return self;
}
self.userName = [decoder decodeObjectForKey:SAMPLEDATA_KEY_USERNAME];
self.gender = [decoder decodeBoolForKey:SAMPLEDATA_KEY_GENDER];
self.age = [decoder decodeIntForKey:SAMPLEDATA_KEY_AGE];
self.friends = [decoder decodeObjectForKey:k_FRIENDS];
self.address = [decoder decodeObjectForKey:k_ADDRESS];
self.addresses = [decoder decodeObjectForKey: k_userEntity_addresses];
}
return self;
}
@end
AddressEntity
//
// AddressEntity.m
// NSCodingDemo
//
// Created by on 11-5-20.
// Copyright 2011 , Inc. All rights reserved.
//
#import " AddressEntity.h "
#define k_Id (@"id")
#define k_AddresEntity_address (@"addrss")
@implementation AddressEntity
@synthesize Id, address;
- ( void )dealloc
{
[self.address release];
[super dealloc];
}
- (NSString * )description
{
return [NSString stringWithFormat: @" id :%d address: %@ " , self.Id, self.address];
}
- ( void )encodeWithCoder:(NSCoder * )coder
{
[coder encodeObject:self.address forKey:k_AddresEntity_address];
[coder encodeInt:self.Id forKey:k_Id];
}
- (id)initWithCoder:(NSCoder * )decoder
{
if (self = [super init])
{
if (decoder == nil)
{
return self;
}
self.address = [decoder decodeObjectForKey:k_AddresEntity_address];
self.Id = [decoder decodeIntForKey:k_Id];
}
return self;
}
@end
// AddressEntity.m
// NSCodingDemo
//
// Created by on 11-5-20.
// Copyright 2011 , Inc. All rights reserved.
//
#import " AddressEntity.h "
#define k_Id (@"id")
#define k_AddresEntity_address (@"addrss")
@implementation AddressEntity
@synthesize Id, address;
- ( void )dealloc
{
[self.address release];
[super dealloc];
}
- (NSString * )description
{
return [NSString stringWithFormat: @" id :%d address: %@ " , self.Id, self.address];
}
- ( void )encodeWithCoder:(NSCoder * )coder
{
[coder encodeObject:self.address forKey:k_AddresEntity_address];
[coder encodeInt:self.Id forKey:k_Id];
}
- (id)initWithCoder:(NSCoder * )decoder
{
if (self = [super init])
{
if (decoder == nil)
{
return self;
}
self.address = [decoder decodeObjectForKey:k_AddresEntity_address];
self.Id = [decoder decodeIntForKey:k_Id];
}
return self;
}
@end
测试代码
-
(IBAction)write:(id)sender
{
// get document path
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex: 0 ];
NSString * filePath = [documentsDirectory stringByAppendingPathComponent:k_FILE_NAME];
NSMutableData * data = [[[NSMutableData alloc] init] autorelease];
NSKeyedArchiver * archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
UserEntity * userEntity = [[[UserEntity alloc] init] autorelease];
userEntity.age = 18 ;
userEntity.gender = NO;
userEntity.userName = @" add " ;
NSArray * friends = [[NSArray alloc] initWithObjects: @" ac " , @" 2 " , @" 3 " , @" 4 " , nil];
userEntity.friends = friends;
AddressEntity * address = [[[AddressEntity alloc] init] autorelease];
address.Id = 1 ;
address.address = @" china " ;
userEntity.address = address;
AddressEntity * address2 = [[[AddressEntity alloc] init] autorelease];
address2.Id = 2 ;
address2.address = @" china2 " ;
AddressEntity * address3 = [[[AddressEntity alloc] init] autorelease];
address3.Id = 3 ;
address3.address = @" china3 " ;
NSArray * addresses = [[NSArray alloc] initWithObjects:address2, address3 , nil];
userEntity.addresses = addresses;
[archiver encodeObject:userEntity forKey: @" KEY " ];
[archiver finishEncoding];
BOOL success = [data writeToFile:filePath atomically:YES];
}
- (IBAction)read:(id)sender
{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex: 0 ];
NSString * filePath = [documentsDirectory stringByAppendingPathComponent:k_FILE_NAME];
NSData * data = [[NSData alloc] initWithContentsOfFile:filePath];
NSKeyedUnarchiver * unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
UserEntity * userEntity = [unArchiver decodeObjectForKey: @" KEY " ];
NSLog( @" name is %@ , friend %@ address :%@ , addresses is :%@ " , userEntity.userName , userEntity.friends , userEntity.address, userEntity.addresses);
}
{
// get document path
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex: 0 ];
NSString * filePath = [documentsDirectory stringByAppendingPathComponent:k_FILE_NAME];
NSMutableData * data = [[[NSMutableData alloc] init] autorelease];
NSKeyedArchiver * archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
UserEntity * userEntity = [[[UserEntity alloc] init] autorelease];
userEntity.age = 18 ;
userEntity.gender = NO;
userEntity.userName = @" add " ;
NSArray * friends = [[NSArray alloc] initWithObjects: @" ac " , @" 2 " , @" 3 " , @" 4 " , nil];
userEntity.friends = friends;
AddressEntity * address = [[[AddressEntity alloc] init] autorelease];
address.Id = 1 ;
address.address = @" china " ;
userEntity.address = address;
AddressEntity * address2 = [[[AddressEntity alloc] init] autorelease];
address2.Id = 2 ;
address2.address = @" china2 " ;
AddressEntity * address3 = [[[AddressEntity alloc] init] autorelease];
address3.Id = 3 ;
address3.address = @" china3 " ;
NSArray * addresses = [[NSArray alloc] initWithObjects:address2, address3 , nil];
userEntity.addresses = addresses;
[archiver encodeObject:userEntity forKey: @" KEY " ];
[archiver finishEncoding];
BOOL success = [data writeToFile:filePath atomically:YES];
}
- (IBAction)read:(id)sender
{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex: 0 ];
NSString * filePath = [documentsDirectory stringByAppendingPathComponent:k_FILE_NAME];
NSData * data = [[NSData alloc] initWithContentsOfFile:filePath];
NSKeyedUnarchiver * unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
UserEntity * userEntity = [unArchiver decodeObjectForKey: @" KEY " ];
NSLog( @" name is %@ , friend %@ address :%@ , addresses is :%@ " , userEntity.userName , userEntity.friends , userEntity.address, userEntity.addresses);
}