总会有一些坑在前面等着你


我们先来看一下后台返回的部分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(_

关于开发中使用writeToFile时的注意事项的更多相关文章

  1. iphone 开发中使用zbar时遇到的几个典型问题解决方法。

    iphone 开发中使用zbar时遇到的几个典型问题解决方法.   在近期的一个ios项目中使用到了一个二维码扫描库(Qrcode)--ZBar, 期间遇到2个问题.   1. zbar下载后使用其l ...

  2. IOS开发中滑动页面时NSTimer停止的问题

    我们在做倒计时的时候,发现当你手指按着屏幕不放,拖动tableView滑动的时候,写在cell上得倒计时停止倒计时,松开继续倒计时.研究发现就是拖动tableView滑动时,NSTimer停止了. 这 ...

  3. 直接添加viewController中的view时的注意事项

    直接添加viewController中的view时需要注意一个问题,比如: MyTestViewController *vc = [MyTestViewController new]; [self.v ...

  4. Android开发中使用数据库时出现java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.

    最近在开发一个 App 的时候用到了数据库,可是在使用数据库的时候就出现了一些问题,在我查询表中的一些信息时出现了一下问题: Caused by: java.lang.IllegalStateExce ...

  5. vue开发中,build时css打包报错

    vue在打包的时候css报错,首先声明的这个并没有解决webpack本身的问题,本来这个也是一个警示,不会影响代码正常运行 这个是因为我在多个页面引入了同一个css文件,webpack打包时候对css ...

  6. 开发中使用UEditor编辑器的注意事项

    最近在一个刚结束的一个项目中使用到了UEditor编辑器,下面总结一下遇到的问题以及使用时需要注意的地方: 1. 使用UEditor插件需要先对其进行路径配置: 在ueditor.config.js文 ...

  7. Golang中进行reslice时的注意事项

    先看下面代码: package main import "fmt" func main() { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} ...

  8. 修改NSMutableArray中的元素时的注意事项

    最近做项目遇到从文件加载数组,并对数组中的元素进行操作的问题,特意写了个Demo,记录下要注意的东西: 代码如下: NSArray *array = @["]; NSMutableArray ...

  9. 在构造函数中使用new时的注意事项

    果然,光看书是没用的,一编程序,很多问题就出现了-- 注意事项: 1. 如果构造函数中适用了new初始化指针成员,则构析函数中必须要用delete 2. new与delete必须兼容,new对应del ...

随机推荐

  1. js正则表达式验证

    有时候会要验证自己写的正则表达式是否正确 所以写了这个小东西: demo:js正则表达式验证 html: <h3>绿色表示匹配,红色表示不匹配</h3> <label&g ...

  2. 创建 Web 前端开发环境(node和npm)

    Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower, Git 和 Grunt. ...

  3. mysql常用博客论坛

    大神博客: starive的博客:http://blog.itpub.net/26435490/viewspace-1133659/ 北在南方的博客:http://blog.itpub.net/226 ...

  4. JavaScript中typeof和instanceof深入详解

    这次主要说说javascript的类型判断函数typeof和判断构造函数原型instanceof的用法和注意的地方. typeof 先来说说typeof吧.首先需要注意的是,typeof方法返回一个字 ...

  5. LNMP 快速安装

    网址是:http://lnmp.org/install.html 值得注意的是:它基本上把所有的扩展都装上了,有点冗余 安装完成后,根目录的位置是 /home/wwwroot/default LNMP ...

  6. oc是一个全动态语言,oc的一切都是基于runtime实现的!

    oc是一个全动态语言,oc的一切都是基于runtime实现的! 从以下三方面来理解runtime吧! 1. 传统的面向过程的语言开发,例如c语言.实现c语言编译器很简单,只要按照语法规则实现一个LAL ...

  7. Java jsp基本结构

    <!DOCTYPE html> <!-- [ published at 2015-11-13 12:30:50 ] --> <html> <head> ...

  8. HDU-5086-Revenge of Segment Tree

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5086 这题太不应该了,比赛时没做出来,本来呢,以现在的水平这题是能够做出来的,可就是题目理解错了,按题 ...

  9. 关于ExtJS必输框,多选项

    必填项: //页面内传值用ID,和后台联系用name <div class="col-xs-4">                     <div class= ...

  10. 程序启动缓慢-原来是hbm.xml doctype的原因

    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "h ...