天天看點

歸檔和偏好設定

由于直接寫入plist檔案的局限性,不能夠存儲自定義對象,是以就有了歸檔,NSString、NSDictionary、NSArray、NSData、NSNumber等類型的對象,可以直接用NSKeyedArchiver進行歸檔和恢複,因為它們内部實作了NSCoding協定,比如NSString實作了NSSecureCoding,而NSSecureCoding實作了NSCoding協定,不是所有的對象都可以直接用這種方法進行歸檔,隻有遵守了NSCoding協定的對象才可以,而歸檔和解檔的過程很像我們在URL請求的時候進行encode和decode的過程,而在歸檔自定義對象的時候,如果子類對象也需要歸檔那麼,在子類對象實作encodeWithCoder和initWithCoder方法的時候要先調用父類的encodeWithCoder和initWithCoder。

歸檔的特點:

–支援複雜的資料對象,包括自定義對象。 –對自定義對象進行歸檔處理,對象中的屬性需要是基本資料類型,或者是實作了NSCoding協定的對象執行個體; –自定義對象的類也需要實作NSCoding;

歸檔和解檔常用方法:

•encodeWithCoder: –每次歸檔對象時,都會調用這個方法。一般在這個方法裡面指定如何歸檔對象中的每個執行個體變量,可以使用encodeObject:forKey:方法歸檔執行個體變量 •initWithCoder: –每次從檔案中恢複(解碼)對象時,都會調用這個方法。一般在這個方法裡面指定如何解碼檔案中的資料為對象的執行個體變量,可以使用decodeObject:forKey:方法解碼執行個體變量

歸檔數組:

//擷取document目錄
    //NSUserDomainMask從使用者檔案夾開始找 YES代表代表展開路徑中的波浪字元“~”
    NSArray *documet=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	
    NSString *doc=documet[0];
    //歸檔 如果歸檔為plist檔案不需要用load的方式加載
    NSString *ahPath=[doc stringByAppendingString:@"array.archive"];
    
    NSArray *[email protected][@"book1",@"book2",@"book3"];
    //歸檔
    [NSKeyedArchiver archiveRootObject:arr toFile:ahPath];
    //解檔
    NSArray *unarray= [NSKeyedUnarchiver unarchiveObjectWithFile:ahPath];
    NSLog(@"array==%@",unarray);
           

歸檔自定義對象

@implementation Person

//歸檔
-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInt:_age forKey:@"age"];
    NSData *imageData=UIImagePNGRepresentation(_image);
 
    [aCoder encodeObject:imageData forKey:@"imageData"];
}

//接檔
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super init];
    if (self) {
        [self setName:[aDecoder decodeObjectForKey:@"name"]];
        [self setAge:[aDecoder decodeIntForKey:@"age"]];
        NSData *imageData=[aDecoder decodeObjectForKey:@"imageData"];
           NSLog(@"%@",imageData);
        [self setImage:[UIImage imageWithData:imageData]];
    }
    return self;
}

+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image{
    Person *person=[[Person alloc]init];
    [person setName:name];
    [person setAge:age];
    [person setImage:image];
    return person;
}
@end
           

自定義對象子類對象

@implementation Student
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super initWithCoder:aDecoder];
    if (self) {
        _no=[aDecoder decodeObjectForKey:@"no"];
    }
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder{
    [super encodeWithCoder:aCoder];
    [aCoder encodeObject:_no forKey:@"no"];
}

+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image no:(NSString *)no{
    Student *stu=[[Student alloc]init];
    [stu setNo:no];
    [stu setAge:age];
    [stu setImage:image];
    [stu setName:name];
    return stu;
}
@end
           

歸檔

NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *doc=arry[0];
    Person *person=[Person initPersonWithName:_nameText.text age:_ageText.text.intValue image:_iconView.image];
    NSString *path=[doc stringByAppendingString:@"person.plist"];
    [NSKeyedArchiver archiveRootObject:person toFile:path];
           

恢複

NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *dir=arry[0];
    NSString *path=[dir stringByAppendingString:@"person.plist"];
   Person *person= [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    _nameText.text=person.name;
    _ageText.text=[NSString stringWithFormat:@"%d",person.age];
    _iconView.image=person.image;
           

使用archiveRootObject:toFile:方法可以将一個對象直接寫入到一個檔案中,但有時候可能想将多個對象寫入到同一個檔案,那麼可以使用NSData來歸檔對象,NSData可以為一些資料提供臨時存儲空間,以便随後寫入檔案,或者存放從磁盤讀取的檔案内容。可以使用[NSMutableDatadata]建立可變資料空間。

歸檔和偏好設定

歸檔多個對象

NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
    
    Person *person1=[Person initPersonWithName:@"san" age:_ageText.text.intValue image:_iconView.image];
     Person *person2=[Person initPersonWithName:@"zhang" age:_ageText.text.intValue image:_iconView.image];
    Student *stu=[Student initPersonWithName:@"lisi" age:10 image:_iconView.image no:@"89757"];
    
    // 建立一塊可變的資料區
    NSMutableData *data = [NSMutableData data];
    
    // 将資料區連接配接到一個NSKeyedArchiver對象
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    
    // 開始存檔對象,存檔的資料都會存儲到NSMutableData中
    [archiver encodeObject:person1 forKey:@"person1"];
    [archiver encodeObject:person2 forKey:@"person2"];
    
    // 存檔完畢(一定要調用這個方法!!!)
    [archiver finishEncoding];
    
    // 将存檔的資料寫入檔案
    [data writeToFile:path atomically:YES];
           

恢複多個對象

NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    // 根據資料,解析成一個NSKeyedUnarchiver對象
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    // 恢複對象
    Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
    Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
    // 恢複完畢(一定要調用這個方法)
    [unarchiver finishDecoding];
           

偏好設定

IOS應用都支援偏好設定,比如儲存使用者名、密碼、字型大小等設定,iOS提供了一套标準的解決方案來為應用加入偏好設定功能,每個應用都有個NSUserDefaults執行個體,通過它來存取偏好設定。

存儲偏好設定

NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    [defaults setObject:@"張三" forKey:@"userName"];
    [defaults setInteger:10 forKey:@"age"];
    [[NSUserDefaults standardUserDefaults]setObject:@"mimaya" forKey:@"password"];
    //同步  如果不加會延遲
    [defaults synchronize];
           

讀取偏好設定

NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    NSString *name=[defaults objectForKey:@"userName"];
    NSLog(@"userName=%@",name);
           

注意:UserDefaults設定資料時,不是立即寫入,而是根據時間戳定時地把緩存中的資料寫入本地磁盤。是以調用了set方法之後資料有可能還沒有寫入磁盤,應用程式就終止了,出現以上問題,可以通過調用synchornize方法強制寫入。