剖析Objective-C持久化教程
剖析Objective-C持久化教程是本文要介紹的內(nèi)容,很詳細(xì)的講解了Objective-C持久化的問題,不多說,我們來看內(nèi)容。
當(dāng)前需求
在做登錄模塊時,需要做登錄的歷史記錄,存儲本機(jī)所有登錄的用戶的用戶名密碼,以及登錄策略如是否記住密碼,是否自動登錄等。具體實現(xiàn)之前,我認(rèn)為這個需求看樣子并不需要SQLite,因為登錄用戶不可能太多,而且存儲的字段也就四個而已,估計用NSUserDefaults存一下數(shù)組就結(jié)了。
初遇困難
令我沮喪的是,這么一個明確的需求竟然一時半會都沒有完成,用戶登陸信息明明很簡單的
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都沒問題,難道是因為沒有存儲數(shù)組么
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 沒辦法只好上網(wǎng)找資料了,這時注意到我存儲的是自定義的結(jié)構(gòu),而和java的序列化類似,在序列化自定義類型的時候,必須要滿足可序列化的一系列條件,甚至包括序列化的規(guī)則,就Objective-C而言,必須要實現(xiàn)NSCoding協(xié)議
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];
- }
這樣,總算可以持久化自定義結(jié)構(gòu)了
和其他類似的語言一樣,基礎(chǔ)的序列化是個說大不大,說小不小的步驟,如果用純c的話,就可以要完全自己去存儲每個字節(jié)再讀出每個字節(jié)然后解釋出來,而現(xiàn)代語言基本上都做好了常見類型的持久化,包括更復(fù)雜的內(nèi)置結(jié)構(gòu)。
但即便如此,編譯器也絕無可能理解用戶自定義的結(jié)構(gòu),就像java里的 transient標(biāo)注,還有持久化中內(nèi)嵌持久化結(jié)構(gòu),持久化時的變量先后依賴關(guān)系等,持久化在網(wǎng)絡(luò)中的傳輸?shù)鹊鹊鹊?,這也遠(yuǎn)遠(yuǎn)超過了本文的范疇 objective-c的困難支持可能要加上一個內(nèi)存的釋放方法不一等,確實很難便利的持久化。
小結(jié):剖析Objective-C持久化教程的內(nèi)容介紹完了,希望本文對你有所幫助!