你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> IOS開發中使用writeToFile時的注意事項

IOS開發中使用writeToFile時的注意事項

編輯:IOS開發綜合

總會有一些坑在前面等著你

我們先來看一下後台返回的部分json數據,稍後再來分析問題,仔細看一下userId和userCode兩個字段,其他不用看

"list": [{
   "classId": 5000285,
   "className": "考勤(A)班",
   "schoolId": 50011,
   "schoolName": "星星局測中學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": "劉玄德"
   }],

問題背景

這個問題是在我集成環信IM的時候,由於需要處理用戶頭像和昵稱問題,所以會將聯系人的頭像url和用戶昵稱做一個本地緩存,緩存的方式就是采用簡單的寫入plist文件來處理.之所以使用plist,是因為簡單方便,而且可以滿足開發,所以就沒有采用其他的緩存方式.

問題就是出現在寫入plist文件上面.

遇到問題

在獲取到後台返回的聯系人數據以後,我就將返回的list進行篩選,只是篩選出所需的用戶姓名和頭像地址.返回字段中,userId和userCode看似一樣,其實解析出來,前者是NSNuber類型,後者是NSString類型,當時只記得後台直接使用SQLite語句,將userCode=userId,根本沒有考慮到類型問題.心想,既然這樣,不如直接使用userId得了,於是將' [userNameDict setObject:dict[@"userName"] forKey:dict[@"userCode"]];'換成了'[userNameDict setObject:dict[@"userName"] forKey:dict[@"userId"]];'.問題就是出現在換了一個字段上.

剛開始沒有發現問題,因為之前一直使用userCode字段取值作為字典的key,所以在本地已經有了緩存.直到有一天,重新安裝App測試時才發現,聊天界面的頭像和昵稱都不在顯示,才最終想到當初換了了一個字段取值.

但是,更換為userId後,打印出來的字典一模一樣,就是writeToFile寫入plist時總是失敗.後來使用isEqualToDictionary方法比較兩個字典又是不一樣的.問題實在難找,當然解決辦法就是切換為原來的userCode,但是遇到問題一向不想通過回避的方式去解決,所以就排查原因,甚至去比較過所有的key和value值,發現還是一樣.最後,感覺實在找不出問題所在,於是去查看返回數據,於是便發現了,字段userId和userCode所對應的Value值的類型是不一樣的.這才得出一下結論

如果是可變字典,那麼在使用'setObject: forKey:'方法時,如果key使用的是NSNumber類型的key,會導致writeToFile失敗.

至於為什麼是這樣,有待進一步研究,當然,如果有人遇到過並找出原因,也可以回復一下,相互學習,共同進步.

附上當時代碼

- (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];
}

分析問題

實際開發當中,總是有細節的東西,雖然有時候覺得,這些東西太基礎,但是就在這些基礎的知識上,我們卻忽略了一些本應該注意的點.好比說我們明明知道向數組中添加元素的時候,元素不能為空,記得考慮為nil,null的情況.這誰都知道,但是卻最容易被忽略,因為你無法確定後台的數據返回什麼,包括那些規范文檔明確要求不能為nil的字段,都有可能返回一個nil or Null .這個時候開始想靜靜了.明白這個世界其實沒有必然的東西.另外,數組越界問題也一直都在,當然為了防止App直接閃退,你可以選擇去覆蓋系統的方法......好了,言歸正傳.我們看一下蘋果官方文檔,回顧一下基礎的東西,文檔中關於NSDictionary和writeToFile有下面兩段內容

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.*

這裡說,字典中的key可以是遵守NSCopying協議的任何對象類型,但是 key-value coding中的key必須是一個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.

這裡描述了寫入文件的對象要求,也就是平時常用的 NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary這些類型,當然自定義類型不可以.

解決問題

當然最後的處理就是將NSNumber格式化為NSString,看下代碼

 NSString *dictKey = [NSString stringWithFormat:@"%@",dict[@"userId"]];
 [userNameDict setObject:dict[@"userName"] forKey:dictKey];

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持本站!

[db:作者簡介][db:原文翻譯及解析]

【IOS開發中使用writeToFile時的注意事項】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved