关于开发中使用writeToFile时的注意事项
总会有一些坑在前面等着你
我们先来看一下后台返回的部分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(_
iphone 开发中使用zbar时遇到的几个典型问题解决方法. 在近期的一个ios项目中使用到了一个二维码扫描库(Qrcode)--ZBar, 期间遇到2个问题. 1. zbar下载后使用其l ... 我们在做倒计时的时候,发现当你手指按着屏幕不放,拖动tableView滑动的时候,写在cell上得倒计时停止倒计时,松开继续倒计时.研究发现就是拖动tableView滑动时,NSTimer停止了. 这 ... 直接添加viewController中的view时需要注意一个问题,比如: MyTestViewController *vc = [MyTestViewController new]; [self.v ... 最近在开发一个 App 的时候用到了数据库,可是在使用数据库的时候就出现了一些问题,在我查询表中的一些信息时出现了一下问题: Caused by: java.lang.IllegalStateExce ... vue在打包的时候css报错,首先声明的这个并没有解决webpack本身的问题,本来这个也是一个警示,不会影响代码正常运行 这个是因为我在多个页面引入了同一个css文件,webpack打包时候对css ... 最近在一个刚结束的一个项目中使用到了UEditor编辑器,下面总结一下遇到的问题以及使用时需要注意的地方: 1. 使用UEditor插件需要先对其进行路径配置: 在ueditor.config.js文 ... 先看下面代码: package main import "fmt" func main() { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} ... 最近做项目遇到从文件加载数组,并对数组中的元素进行操作的问题,特意写了个Demo,记录下要注意的东西: 代码如下: NSArray *array = @["]; NSMutableArray ... 果然,光看书是没用的,一编程序,很多问题就出现了-- 注意事项: 1. 如果构造函数中适用了new初始化指针成员,则构析函数中必须要用delete 2. new与delete必须兼容,new对应del ... 准备: 创建一个成绩表 Create table grade (id integer, score integer); 插入数据(只有id每次加一,score是1到100的随机数,java生成): p ... K-Means 算法 在数据挖掘中, k-Means 算法是一种 cluster analysis 的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 问题 K-Means ... Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当 ... AngularJS指令进阶 – ngModelController详解 在自定义Angular指令时,其中有一个叫做require的字段,这个字段的作用是用于指令之间的相互交流.举个简单的例子,假如我 ... 引言 现在做游戏开发的没有几个不用Excel的,用的最多的就是策划.尤其是数值策划,Excel为用户提供强大的工具,各种快捷键,各种插件,各种函数.但是作为程序来说其实关注的不是Excel而是它最终形 ... spark算子大致上可分三大类算子: 1.Value数据类型的Transformation算子,这种变换不触发提交作业,针对处理的数据项是Value型的数据. 2.Key-Value数据类型的Tran ... window.open a.href打开窗口referer的问题: JSP: <%@ page language="java" import="java.util. ... 方法调用模式:函数调用模式:构造器调用模式:apply调用模式: 方法调用模式: 当一个函数被保存为对象的一个属性时,我们称它为一个方法.当一个方法被调用时,this被绑定到该对象. 函数调用模式: ... 进行GET方法的测试 #telnet[ ]10.1.1.11[ ]80 GET[ ]/[ ]HTTP/1.0 [两个回车] HEAD[]/[]HTTP/1.0[回车回车] http://www.cnb ... 经过几天的得瑟,今天终于开始实践IOS开发了.由于没有苹果的电脑,现在先用虚拟机凑合着. 第一个开发的东西就是苹果官方向导里的helloworld了.最后在运行的时候有一个异常,导致程序会闪退,错误信 ...关于开发中使用writeToFile时的注意事项的更多相关文章
随机推荐