IOS開(kāi)發(fā)中使用writeToFile時(shí)的注意事項(xiàng)
總會(huì)有一些坑在前面等著你
我們先來(lái)看一下后臺(tái)返回的部分json數(shù)據(jù),稍后再來(lái)分析問(wèn)題,仔細(xì)看一下userId和userCode兩個(gè)字段,其他不用看
"list": [{ "classId": 5000285, "className": "考勤(A)班", "schoolId": 50011, "schoolName": "星星局測(cè)中學(xué)25", "classLeaderUserId": 2000163, "parentList": [{ "userId": 2000790, "userName": "zhaomin", "gender": "0", "mobile": "15071362222", "email": "", "areaCode": "440105", "avatarUrl": "", "userCode": "2000790", "id": 1542, "roleType": 2, "nickName": "zhaomin" }, { "userId": 2000846, "userName": "劉玄德", "gender": "1", "mobile": "18825113388", "email": "", "areaCode": "440105", "avatarUrl": "", "userCode": "2000846", "id": 1631, "roleType": 2, "nickName": "劉玄德" }],
問(wèn)題背景
這個(gè)問(wèn)題是在我集成環(huán)信IM的時(shí)候,由于需要處理用戶(hù)頭像和昵稱(chēng)問(wèn)題,所以會(huì)將聯(lián)系人的頭像url和用戶(hù)昵稱(chēng)做一個(gè)本地緩存,緩存的方式就是采用簡(jiǎn)單的寫(xiě)入plist文件來(lái)處理.之所以使用plist,是因?yàn)楹?jiǎn)單方便,而且可以滿(mǎn)足開(kāi)發(fā),所以就沒(méi)有采用其他的緩存方式.
問(wèn)題就是出現(xiàn)在寫(xiě)入plist文件上面.
遇到問(wèn)題
在獲取到后臺(tái)返回的聯(lián)系人數(shù)據(jù)以后,我就將返回的list進(jìn)行篩選,只是篩選出所需的用戶(hù)姓名和頭像地址.返回字段中,userId和userCode看似一樣,其實(shí)解析出來(lái),前者是NSNuber類(lèi)型,后者是NSString類(lèi)型,當(dāng)時(shí)只記得后臺(tái)直接使用Sqlite語(yǔ)句,將userCode=userId,根本沒(méi)有考慮到類(lèi)型問(wèn)題.心想,既然這樣,不如直接使用userId得了,于是將' [userNameDict setObject:dict[@"userName"] forKey:dict[@"userCode"]];'換成了'[userNameDict setObject:dict[@"userName"] forKey:dict[@"userId"]];'.問(wèn)題就是出現(xiàn)在換了一個(gè)字段上.
剛開(kāi)始沒(méi)有發(fā)現(xiàn)問(wèn)題,因?yàn)橹耙恢笔褂胾serCode字段取值作為字典的key,所以在本地已經(jīng)有了緩存.直到有一天,重新安裝App測(cè)試時(shí)才發(fā)現(xiàn),聊天界面的頭像和昵稱(chēng)都不在顯示,才最終想到當(dāng)初換了了一個(gè)字段取值.
但是,更換為userId后,打印出來(lái)的字典一模一樣,就是writeToFile寫(xiě)入plist時(shí)總是失敗.后來(lái)使用isEqualToDictionary方法比較兩個(gè)字典又是不一樣的.問(wèn)題實(shí)在難找,當(dāng)然解決辦法就是切換為原來(lái)的userCode,但是遇到問(wèn)題一向不想通過(guò)回避的方式去解決,所以就排查原因,甚至去比較過(guò)所有的key和value值,發(fā)現(xiàn)還是一樣.最后,感覺(jué)實(shí)在找不出問(wèn)題所在,于是去查看返回?cái)?shù)據(jù),于是便發(fā)現(xiàn)了,字段userId和userCode所對(duì)應(yīng)的Value值的類(lèi)型是不一樣的.這才得出一下結(jié)論
如果是可變字典,那么在使用'setObject: forKey:'方法時(shí),如果key使用的是NSNumber類(lèi)型的key,會(huì)導(dǎo)致writeToFile失敗.
至于為什么是這樣,有待進(jìn)一步研究,當(dāng)然,如果有人遇到過(guò)并找出原因,也可以回復(fù)一下,相互學(xué)習(xí),共同進(jìn)步.
附上當(dāng)時(shí)代碼
- (void)saveContactListDict:(id)list { NSMutableArray *contactListArray = [NSMutableArray array]; for (NSDictionary *dict in list) { for (NSString *key in dict) { if ([dict[key] isKindOfClass:[NSArray class]]) { [contactListArray addObjectsFromArray:dict[key]]; } } } NSMutableDictionary *userNameDict = [NSMutableDictionary dictionary]; NSMutableDictionary *avatarurlDict = [NSMutableDictionary dictionary]; NSMutableDictionary *avatarurlAndNameDict = [NSMutableDictionary dictionary]; for (NSDictionary *dict in contactListArray) { if (dict[@"userId"] == nil) { return; } [userNameDict setObject:dict[@"userName"] forKey:dict[@"userId"]]; NSString *url =dict[@"avatarUrl"]; NSString *avatarUrl = [CPUtil getThumUrl:url size:CGSizeMake(200, 200)]; [avatarurlDict setObject:avatarUrl forKey:dict[@"userId"]]; if (dict[@"userName"] == nil) { return; } [avatarurlAndNameDict setObject:avatarUrl forKey:dict[@"userName"]]; } NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; NSString *userNameDictPath = [path stringByAppendingPathComponent:@"userNameDict.plist"]; NSString *avatarurlDictPath = [path stringByAppendingPathComponent:@"avatarurlDict.plist"]; NSString *avatarurlAndNameDictPath = [path stringByAppendingPathComponent:@"avatarurlAndNameDict.plist"]; [userNameDict writeToFile:userNameDictPath atomically:YES]; [avatarurlDict writeToFile:avatarurlDictPath atomically:YES]; [avatarurlAndNameDict writeToFile:avatarurlAndNameDictPath atomically:YES]; }
分析問(wèn)題
實(shí)際開(kāi)發(fā)當(dāng)中,總是有細(xì)節(jié)的東西,雖然有時(shí)候覺(jué)得,這些東西太基礎(chǔ),但是就在這些基礎(chǔ)的知識(shí)上,我們卻忽略了一些本應(yīng)該注意的點(diǎn).好比說(shuō)我們明明知道向數(shù)組中添加元素的時(shí)候,元素不能為空,記得考慮為nil,null的情況.這誰(shuí)都知道,但是卻最容易被忽略,因?yàn)槟銦o(wú)法確定后臺(tái)的數(shù)據(jù)返回什么,包括那些規(guī)范文檔明確要求不能為nil的字段,都有可能返回一個(gè)nil or Null .這個(gè)時(shí)候開(kāi)始想靜靜了.明白這個(gè)世界其實(shí)沒(méi)有必然的東西.另外,數(shù)組越界問(wèn)題也一直都在,當(dāng)然為了防止App直接閃退,你可以選擇去覆蓋系統(tǒng)的方法......好了,言歸正傳.我們看一下蘋(píng)果官方文檔,回顧一下基礎(chǔ)的東西,文檔中關(guān)于NSDictionary和writeToFile有下面兩段內(nèi)容
NSDictionary
*A key-value pair within a dictionary is called an entry. Each entry consists of one object that represents the key and a second object that is that key's value. Within a dictionary, the keys are unique. That is, no two keys in a single dictionary are equal (as determined by isEqual(_:)). In general, a key can be any object (provided that it conforms to the NSCopying protocol—see below), but note that when using key-value coding the key must be a string (see Accessing Object Properties). Neither a key nor a value can be nil; if you need to represent a null value in a dictionary, you should use NSNull.*
這里說(shuō),字典中的key可以是遵守NSCopying協(xié)議的任何對(duì)象類(lèi)型,但是 key-value coding中的key必須是一個(gè)string.
'- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;'
This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
這里描述了寫(xiě)入文件的對(duì)象要求,也就是平時(shí)常用的 NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary這些類(lèi)型,當(dāng)然自定義類(lèi)型不可以.
解決問(wèn)題
當(dāng)然最后的處理就是將NSNumber格式化為NSString,看下代碼
NSString *dictKey = [NSString stringWithFormat:@"%@",dict[@"userId"]]; [userNameDict setObject:dict[@"userName"] forKey:dictKey];
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
iOS無(wú)障礙適配西瓜視頻Voice?Over實(shí)踐示例
本文從研發(fā)的視角出發(fā),講述了如何使用?Voice?Over、如何適配?Voice?Over?以及適配過(guò)程中如果遇到問(wèn)題應(yīng)該如何解決。希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05iOS利用NSAttributedString實(shí)現(xiàn)圖文混排效果示例
iOS7以后,因?yàn)門(mén)extKit的強(qiáng)大,可以用NSAttributedString很方便的實(shí)現(xiàn)圖文混排(主要是利用了NSTextAttachment),所以下面這篇文章主要給大家介紹了關(guān)于iOS利用NSAttributedString實(shí)現(xiàn)圖文混排效果的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10簡(jiǎn)介Objective-C解析XML與JSON數(shù)據(jù)格式的方法
這篇文章主要介紹了Objective-C解析XML與JSON數(shù)據(jù)格式的方法,文中解析JSON包括拼接JSON字符串用到了SBJson這個(gè)解析器,需要的朋友可以參考下2016-01-01iOS中讓多個(gè)cell上都出現(xiàn)倒計(jì)時(shí)的分析與實(shí)現(xiàn)
這篇文章主要給大家介紹了在iOS中每個(gè)cell上都出現(xiàn)倒計(jì)時(shí)的分析與實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2017-07-07iOS 中使用tableView實(shí)現(xiàn)右滑顯示選擇功能
這篇文章主要介紹了iOS 中使用tableView實(shí)現(xiàn)右滑顯示選擇功能的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07iOS開(kāi)發(fā)中以application/json上傳文件實(shí)例詳解
在和sever后臺(tái)交互的過(guò)程中、有時(shí)候、他們需要我們iOS開(kāi)發(fā)者以“application/json”形式上傳,具體實(shí)例代碼大家參考下本文2017-07-07MacOS無(wú)法掛載NFS Operation not permitted錯(cuò)誤解決辦法
這篇文章主要介紹了MacOS無(wú)法掛載NFS Operation not permitted錯(cuò)誤解決辦法的相關(guān)資料2017-02-02Framework中實(shí)現(xiàn)OC和Swift的混編方案
這篇文章主要為大家介紹了Framework中實(shí)現(xiàn)OC和Swift的混編方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01