菜鸟程序猿的爬坑日记(一)
1.NSDictionary初始化
乱入有关通知NSNotification(有点扯淡):很少用通知,今天随手写了个通知传值,死活传不过去,打断点找了半天也没发现,最后是朋友发现了,发送和接收的通知名写的不一致。。。我也是醉,以后还是习惯性地把通知名抽成宏吧!!
后来还发现一个问题:当时我在项目中的需求是点击A控制器的cell创建并push跳转到B控制器再跳转到C,而在C中我需要拿到A中所选Cell的模型中的一个属性值id来作为C中数据请求的一个参数,总之我就是要从A到C进行值传递,于是我就试着采用了通知,结果发现在A push B 之前 发送通知,在C中注册监听,但结果发现监听通知的方法并没有执行。那这里我个人初步认定是 因为通知发送出去的时候C还没有实例化,也就还没有注册监听接收到通知,当然了由于我是自学,加之通知基本没怎么用过,而且自己学习的时候值传递一般都是A到B,或者B到A,这种情况还是第一次,所以权威原因尚不敢肯定(日后求证了来记一笔。。)不过我认为八九不离十,可以在A中创建子线程,常驻,在while循环中不断发送通知,这样就应该能接收到了。-_-!我最后还是采用在B和C中设置属性来接收,从A传到B再传到C,轻松搞定!(其实当初也是犯贱要尝试用不熟练的传值方式,目前了解的传值:1.属性接收、2.代理delegate、3.block、4.通知NSNotification、5.NSUserDefault、6单例等)。。。。
Objective-C中,NSDictionary初始化的方法有很多种
方法1: [NSDictionary dictionaryWithObjectsAndKeys:<#(id), ...#>, nil] 方法2: NSDictionary *dic = @{@"key":value}
坑在哪里?
坑就在第二种初始化方法 NSDictionary *dic = @{@"key":value}
它到底是如何坑的呢?
如果你的value是为nil 必将引发崩溃:
'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]
意思就是说使用[__NSPlaceholderDictionary initWithObjects:forKeys:count:]这个初始化方法,发现keys count和objcects的个数不匹配了
如何规避?
在使用@{@”key”:value} 这种方式初始化的时候,一定要对value做是否为nil的判断,为nil就不要加入Dictionary
或
使用标准的初始化方法:
NSDictionary dictionaryWithObjectsAndKeys:value1,@"v1",value2,@"v2",value3,@"v3", nil];
或其它的几个初始化方法进行初始化,这样如果value为nil就不会加入字典,使用 objectForKey:取出来的对象就会为nil对象,不会引发崩溃。
关联:
使用@[]方法初始化NSArray也有此坑,规避方法同字典一样
2.字典转模型
之前写吐了的代码,用了MJExtension之后好久没写了。。
+ (instancetype)shopWithDict:(NSDictionary *)dict { DLShop *shop = [[self alloc] init]; [shop setValuesForKeysWithDictionary:dict]; return shop; }
或者
-(instancetype)initWithDict:(NSDictionary *)dict { if (self = [super init]) { [self setValuesForKeysWithDictionary:dict]; } return self; } + (instancetype)shopWithDict:(NSDictionary *)dict { return [[self alloc] initWithDict:dict]; }
在模型的.h文件里面提供属性接口和这两个实例化方法,在.m文件里实现他们
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
上面方法的头文件: Given a dictionary containing keyed attribute values, to-one-related objects, and/or collections of to-many-related objects, set the keyed values. Dictionary entries whose values are NSNull result in -setValue:nil forKey:key messages being sent to the receiver.(有关NSNull)
今天遇到的坑,
崩在这里了,太年轻,找了半天,浪费不少时间,最终发现是模型的属性少写了一个,如上图,字典里面有八个键值对,模型属性只有5个。(至于为什么会发生如下的无线调用导致内存崩溃,尚不得知-_-!)总之在这里模型属性只能多不能少!模型属性只能多不能少!模型属性只能多不能少!重要的事情要说三遍
用
- (void)setValuesForKeysWithDictionary:
这个方法还需要注意一点,字典里面的键值(key)必须和属性名一一对应(一样),遇到id。。等关键字时:
由于属性很多。手工写setvalue太麻烦
- (void)setValue:(id)value forUndefinedKey:(NSString *)key { if([key isEqualToString:@"id"]) self.userid = value;
这时只需要重写- (void)setValue:(id)value forUndefinedKey:(NSString *)key 方法即可
并把声明 中的id改为userid
@property (nonatomic,strong) NSString *userid;
这样一来执行程序快速,还省去了不少手工代码。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key { if([key isEqualToString:@"id"]) { key = @"shop_id"; } [super setValue:value forKey:key]; // [super setValue:value forUndefinedKey:key];应该是上面的,敲的时候看着点 }
或者像上面那样
- (void)setValue:(id)value forUndefinedKey:(NSString *)key { if([key isEqualToString:@"id"]) { self.shop_id = value; } }
对于我现在常用的MJExtension,顺带也在这里记一笔:
比较常用的
1. Plist → 模型数组
控制器中引用#import "MJExtension.h"
模型数组 = [模型类名 objectArrayWithFilename:@"文件名.plist"];
2. 对NSLog的优化,解决 调试时,打印模型,只打印出内存地址的问题
使用方法:在模型类的.m文件中,引用#import "MJExtension.h"
在@implementation 和 @end之间,写上MJLogAllIvrs
3. 对NSCoding的优化,不用再写繁琐的解档和归档方法了
使用方法:在模型类的.m文件中,引用#import "MJExtension.h"
在@implementation 和 @end之间,写上MJCodingImplementation
4. 字典数组 → 模型数组
4.1 场景一: [ 字典1,
字典2,
字典3 ]
如果每个字典都是一个模型,可以用
NSArray *modelArray = [模型类名 objectArrayWithKeyValuesArray:字段数组];
4.2 场景二:在场景一的基础上,每个字典里面,有数组(假设数组的key值是arrayName),数组里面存放着若干个相同的模型,使用下面的方法
使用方法:
首先在模型类.m文件中,引入#import "MJExtension.h"
然后在 @implementation 和 @end之间 写上
- (NSDictionary *)objectClassInArray { return @{@"arrayName" : [模型类名 class]}; }
5. 如果 服务器传过来的 字典数组里的字典的Key,是OC里的关键字,而使用MJExtention的前提是,模型里的属性名和数组的key一致才行(区分大小写),怎么办?
使用replacedKeyFromPropertyName
使用方法:1.在模型类.m文件引入"MJExtension.h"
2.实现方法
+ (NSDictionary *)replacedKeyFromPropertyName { return @{@“非关键字的属性名” : @“数组的key”}; }
6. 单个字典 → 单个模型
+ (instancetype)objectWithKeyValues:(NSDictionary *)keyValues
公司的旧项目里面用的Mantle,github上星星爆表的牛B框架,(但是忘的差不多了,0.0.。。MJ大神在一天就用它了,MJExtension)这里附上南峰子大神的关于mantle的博客链接,大神的博客值得学习
第一篇就写到这,都是小问题,太年轻,后续应该陆续会有很多类似篇,主要是自己增强印象,大神见谅。。。。