菜鸟程序猿的爬坑日记(一)

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太麻烦

+ (instancetype)picinfo:(NSDictionary *)dict
{
    PicModel *picmodel = [[self alloc] init];
    [picmodel setValuesForKeysWithDictionary:dict];
    return picmodel;
}

单纯的运行setValuesForKeysWithDictionary是必然core的

   
- (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的博客链接,大神的博客值得学习

  第一篇就写到这,都是小问题,太年轻,后续应该陆续会有很多类似篇,主要是自己增强印象,大神见谅。。。。

 
 
 
 
 
posted @ 2015-12-15 22:47  MysticCoder  阅读(819)  评论(2编辑  收藏  举报