剖析Objective-C持久化教程

剖析Objective-C持久化教程是本文要介绍的内容,很详细的讲解了Objective-C持久化的问题,不多说,我们来看内容。

当前需求

在做登录模块时,需要做登录的历史记录,存储本机所有登录的用户的用户名密码,以及登录策略如是否记住密码,是否自动登录等。具体实现之前,我认为这个需求看样子并不需要SQLite,因为登录用户不可能太多,而且存储的字段也就四个而已,估计用NSUserDefaults存一下数组就结了。

初遇困难

令我沮丧的是,这么一个明确的需求竟然一时半会都没有完成,用户登陆信息明明很简单的

Objective-c代码

@interface LoginUserInfo : NSObject     


{     


    NSString *username_;     


    NSString *password_;     


    BOOL     remember_;     


    BOOL     autoLogin_;     


}     


    


@property (nonatomic, copy) NSString *username;     


@property (nonatomic, copy) NSString *password;     


@property (nonatomic, assign) BOOL remember;     


@property (nonatomic, assign) BOOL autoLogin;     


@end     


      


@protocol LoginHistoryDelegate;    


 


@interface LoginUserInfo : NSObject  


{  


    NSString *username_;  


    NSString *password_;  


    BOOL     remember_;  


    BOOL     autoLogin_;  


}  


 


@property (nonatomic, copy) NSString *username;  


@property (nonatomic, copy) NSString *password;  


@property (nonatomic, assign) BOOL remember;  


@property (nonatomic, assign) BOOL autoLogin;  


@end  


   


@protocol LoginHistoryDelegate;   

存取的时候也很简单

Objective-c代码 

// 增加一个用户要看是否是新用户,如果是新的就增加,否则要修改     


- (void)addUser:(LoginUserInfo *)info     


{     



    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     




    NSArray *list = [self getUserList];     




    NSArray *newList = nil;     




    if (list == nil)     



    {     



        newList = [NSArray arrayWithObject:info];     



    }     


    else     


    {     



        NSMutableArray *mutList = [[NSMutableArray alloc] initWithCapacity:[list count]+1];     



        [mutList addObject:info];     


        for (LoginUserInfo *user in list)     


        {     


            if (![[info username] isEqualToString:[user username]])     


            {     


                [mutList addObject:user];     


            }     


        }     



        newList = [mutList mutableCopy];     



    }     


    [defaults setObject:newList forKey:kUserHistoryKey];     


    [defaults synchronize];     


    [newList release];     


}     


    


- (NSArray *)getUserList     


{     



    NSArray *objectArray = [[NSUserDefaults standardUserDefaults]  objectForKey:kUserHistoryKey];     



    return objectArray;     


}    


 


// 增加一个用户要看是否是新用户,如果是新的就增加,否则要修改  


- (void)addUser:(LoginUserInfo *)info  


{  



    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  




    NSArray *list = [self getUserList];  




    NSArray *newList = nil;  




    if (list == nil)  



    {  



        newList = [NSArray arrayWithObject:info];  



    }  


    else  


    {  



        NSMutableArray *mutList = [[NSMutableArray alloc] initWithCapacity:[list count]+1];  



        [mutList addObject:info];  


        for (LoginUserInfo *user in list)  


        {  


            if (![[info username] isEqualToString:[user username]])  


            {  


                [mutList addObject:user];  


            }  


        }  



        newList = [mutList mutableCopy];  



    }  


    [defaults setObject:newList forKey:kUserHistoryKey];  


    [defaults synchronize];  


    [newList release];  


}  


 


- (NSArray *)getUserList  


{  



    NSArray *objectArray = [[NSUserDefaults standardUserDefaults]  objectForKey:kUserHistoryKey];  



    return objectArray;  


} 

但这样无论我怎么存储用户列表,在getUserList的时候获得的始终是nil。

各种尝试

难道是NSUserdefaults有问题么?我试了试在同个方法里改为存储普通的int,bool,甚至NSString都没问题,难道是因为没有存储数组么

Objective-c代码

NSArray *arr = [NSArray arrayWithObjects:@"xixi", @"haha", nil];     


    [[NSUserDefaults standardUserDefaults] setObject:arr forKey:@"Array"];     


    [[NSUserDefaults standardUserDefaults] synchronize];     



     NSArray *arr2 = [[NSUserDefaults standardUserDefaults] objectForKey:@"Array"];     




    NSString *s1 = [arr2 objectAtIndex:0];     



    NSLog(@"%@", s1);    


 



NSArray *arr = [NSArray arrayWithObjects:@"xixi", @"haha", nil];  



    [[NSUserDefaults standardUserDefaults] setObject:arr forKey:@"Array"];  


    [[NSUserDefaults standardUserDefaults] synchronize];  



     NSArray *arr2 = [[NSUserDefaults standardUserDefaults] objectForKey:@"Array"];  




    NSString *s1 = [arr2 objectAtIndex:0];  



    NSLog(@"%@", s1);  

但此时仍然可以很顺利的显示出s1为xixi 没办法只好上网找资料了,这时注意到我存储的是自定义的结构,而和java的序列化类似,在序列化自定义类型的时候,必须要满足可序列化的一系列条件,甚至包括序列化的规则,就Objective-C而言,必须要实现NSCoding协议

Objective-c代码

- (void)encodeWithCoder:(NSCoder *)coder;     


{     


    [coder encodeObject:username_ forKey:@"username"];     


    [coder encodeObject:password_ forKey:@"password"];     


    [coder encodeBool:remember_ forKey:@"remember"];     


    [coder encodeBool:autoLogin_ forKey:@"autologin"];     


}     


      


- (id)initWithCoder:(NSCoder *)coder;     


{     



    self = [[LoginUserInfo alloc] init];     



    if (self != nil)     


    {     



        self.username = [coder decodeObjectForKey:@"username"];     




        self.password = [coder decodeObjectForKey:@"password"];     




        self.remember = [coder decodeBoolForKey:@"remember"];     




        self.autoLogin = [coder decodeBoolForKey:@"autologin"];     



    }     


        


    return self;     


}    


 


- (void)encodeWithCoder:(NSCoder *)coder;  


{  


    [coder encodeObject:username_ forKey:@"username"];  


    [coder encodeObject:password_ forKey:@"password"];  


    [coder encodeBool:remember_ forKey:@"remember"];  


    [coder encodeBool:autoLogin_ forKey:@"autologin"];  


}  


   


- (id)initWithCoder:(NSCoder *)coder;  


{  



    self = [[LoginUserInfo alloc] init];  



    if (self != nil)  


    {  



        self.username = [coder decodeObjectForKey:@"username"];  




        self.password = [coder decodeObjectForKey:@"password"];  




        self.remember = [coder decodeBoolForKey:@"remember"];  




        self.autoLogin = [coder decodeBoolForKey:@"autologin"];  



    }  


     


    return self;  


}   

然后在存取的时候再加上序列化以及反序列化的代码

Objective-c代码

- (NSArray *)getUserList     


{     



    NSArray *objectArray = nil;     




    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kUserHistoryKey];     



    if (data != nil)     


    {     



        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];     



        if (oldSavedArray != nil)     



            objectArray = [[NSArray alloc] initWithArray:oldSavedArray];     



//        else     



//            objectArray = [[NSMutableArray alloc] init];     



    }     


    return objectArray;     


}     


    


// 增加一个用户要看是否是新用户,如果是新的就增加,否则要修改     


- (void)addUser:(LoginUserInfo *)info     


{     



    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     




    NSArray *list = [self getUserList];     




    NSArray *newList = nil;     




    if (list == nil)     



    {     



        newList = [NSArray arrayWithObject:info];     



    }     


    else     


    {     



        NSMutableArray *mutList = [[NSMutableArray alloc] initWithCapacity:[list count]+1];     



        [mutList addObject:info];     


        for (LoginUserInfo *user in list)     


        {     


            if (![[info username] isEqualToString:[user username]])     


            {     


                [mutList addObject:user];     


            }     


        }     



        newList = [mutList mutableCopy];     



    }     


    [defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:     


newList] forKey:kUserHistoryKey];     


    [defaults synchronize];     


    [newList release];     


}    


 


- (NSArray *)getUserList  


{  



    NSArray *objectArray = nil;  




    NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kUserHistoryKey];  



    if (data != nil)  


    {  



        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];  



        if (oldSavedArray != nil)  



            objectArray = [[NSArray alloc] initWithArray:oldSavedArray];  



//        else  



//            objectArray = [[NSMutableArray alloc] init];  



    }  


    return objectArray;  


}  


 


// 增加一个用户要看是否是新用户,如果是新的就增加,否则要修改  


- (void)addUser:(LoginUserInfo *)info  


{  



    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];  




    NSArray *list = [self getUserList];  




    NSArray *newList = nil;  




    if (list == nil)  



    {  



        newList = [NSArray arrayWithObject:info];  



    }  


    else  


    {  



        NSMutableArray *mutList = [[NSMutableArray alloc] initWithCapacity:[list count]+1];  



        [mutList addObject:info];  


        for (LoginUserInfo *user in list)  


        {  


            if (![[info username] isEqualToString:[user username]])  


            {  


                [mutList addObject:user];  


            }  


        }  



        newList = [mutList mutableCopy];  



    }  


    [defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:  


newList] forKey:kUserHistoryKey];  


    [defaults synchronize];  


    [newList release];  


} 

这样,总算可以持久化自定义结构了

和其他类似的语言一样,基础的序列化是个说大不大,说小不小的步骤,如果用纯c的话,就可以要完全自己去存储每个字节再读出每个字节然后解释出来,而现代语言基本上都做好了常见类型的持久化,包括更复杂的内置结构。

相关推荐