携手创作,一起生长!这是我参与「日新方案 8 月更文挑战」的第21天,点击查看活动概况

前言

字典转模型


/** 一般完成字典实例化模型,都完成了以下模型的实例化办法*/
//运用字典实例化模型
- (instancetype) initWithDictionary :(NSDictionary *) appDictionary;
//类办法可以快速实例化一个目标--把代码放在它最应该呆的当地
+ (instancetype) appInfoWithDictionary : (NSDictionary *) appDictionary;
//回来plist文件对应的模型数组 ,运用懒加载

KVC的赋值

- (instancetype) initWithDictionary:(NSDictionary *)appDictionary{
    //self is object
    self = [super init];
    if (self) {//已然nil解析成NO,所以没有必要在条件句子比较。不要拿某样东西直接与YES比较,由于YES被界说为1
        //init local vars 将plist文件的信息在此处进行字典转模型
        //KVC (key value coding) 键值编码:是一种直接修正、读取目标特点的一种办法;KVC被称为cocoa的大招
        [self setValuesForKeysWithDictionary:appDictionary];//本质上是调用        self setValue:<#(nullable id)#> forUndefinedKey:(nonnull NSString *)
    }
    return self;
}

I 字典转模型

  • 运用字典的害处

一般取出和修正数据字典的数据,都要通过编写“字符串类型”的key值-》编辑器IDE没有智能提示、手动写key简略写错,且此时IDE不会有任何的警告和报错。 字典的运用比方

dict[@"name"] = @"Jack";
NSString *name = dict[@"name"];
  • 运用数据模型的好处

1)数据模型(专门用来存放数据的目标),运用数据模型表示数据更专业些 2)运用模型修正数据、读取数据均选用目标的特点,进步编写功率

1.1 字典转模型的完成过程

1)字典转模型的进程,一般被封装在模型内部 2)模型应该供给一个“带有NSDictionary类型”参数的构造办法

- (instancetype)initWithDict:(NSDictionary*)dict;
+ (instancetype)xxxWithDict:(NSDictionary*)dict;

1.2 字典转模型的进程

  • [选用KVC(keyValueCoding)完成] plist文件解析-》字典数组(NSDictionary)-》模型数组(AppInfo)

运用字典实例化模型 (把代码放在它最应该呆的当地)

- (instancetype) initWithDictionary:(NSDictionary *)appDictionary{
    //self is object
    self = [super init];
    if (self) {//已然nil解析成NO,所以没有必要在条件句子比较。不要拿某样东西直接与YES比较,由于YES被界说为1
        //init local vars 将plist文件的信息在此处进行字典转模型
        //KVC (key value coding) 键值编码:是一种直接修正、读取目标特点的一种办法;KVC被称为cocoa的大招
        [self setValuesForKeysWithDictionary:appDictionary];     
    }
    return self;
}
//运用类办法完成“字典实例化模型”--地道的代码
+ (instancetype) appInfoWithDictionary:(NSDictionary *)appDictionary{
    //self is class
    return [[self alloc]initWithDictionary:appDictionary];//+ (instancetype)alloc    Description    Returns a new instance of the receiving class.   
}
@end
  • 运用KVC的注意事项:

1、plist文件中的键值名称必须与模型目标的特点名称共同 2、模型中的特点,可以不全部出现在plist文件中

II 目标的持平性 & 本体性

  1. 一个目标的本体和它的内存地址是相关联的。 NSObject 的isEqual:本质上是对本体性的查看,即两个 NSObject 假如指向了同一个内存地址,那它们就被认为是相同的。

  2. 当两个物体有一系列相同的可观测的特点时,两个物体可能是互相持平

2.1 持平性查看

目标持平性查看的首要运用场景:确定一个目标是不是一个调集的成员,关于 NSArray,NSDictionary 和 NSString 容器类来说,更加有用的是进行持平性查看,即关于调集中的每个成员进行判别,因此咱们需求重写isEqual:

重写 isEqual:

  1. 先进行本体性查看,假如失败,就进行实际内容(意义)上的比较,比方判别其中几个首要特性的特点。
- (BOOL)isEqual:(id)object {
  if (self == object) {
    return YES;
  }
  if (![object isKindOfClass:[Person class]]) {
    return NO;
  }
  return [self isEqualToPerson:(Person *)object];//要害特点的判别,比方身份证ID
}
  1. 重写 hash 办法,便于快速地(O(1)) 进行元素查找。

相关于数组把元素按次序存储(0, 1, …, n-1),散列表在内存中分配 n 个方位,然后运用一个散列函数来计算出方位规模之内的某个具体方位。

hash 得到的值不必是仅有可区别的,假如发生了散列磕碰,散列表会从磕碰发生的方位开始向后寻觅,把新的元素放在第一个可供放置的方位。

@implementation NSDate (ex)
- (NSUInteger)hash {
  return (NSUInteger)abs([self timeIntervalSinceReferenceDate]);
}

对要害特点的散列值进行一个简略的二进制移位操作,即可简略的完成目标的hash 函数:


@implementation UIColor (ex)
/**
>左移运算符(<<):按二进制形式把所有的数字向左移动对应的位数,高位移出(放弃),低位的空位补零。
*/
- (NSUInteger)hash {
  CGFloat red, green, blue;
  [self getRed:&red green:&green blue:&blue alpha:nil];
  return ((NSUInteger)(red * 255) << 16) + ((NSUInteger)(green * 255) << 8) + (NSUInteger)(blue * 255);
}
@end

对要害特点的散列值进行一个简略的XOR操作

/**
异或 ^ 相同为0,不相同为1;
运用场景:密码加密、散列值计算。
*/
- (NSUInteger)hash {
  return [self.id hash] ^ [self.birthday hash];
}

2.2 Foundation 框架中,自己完成的持平性查看

  • NSAttributedString -isEqualToAttributedString:
  • NSData -isEqualToData:
  • NSDate -isEqualToDate:
  • NSDictionary -isEqualToDictionary:
  • NSHashTable -isEqualToHashTable:
  • NSIndexSet -isEqualToIndexSet:
  • NSNumber -isEqualToNumber:
  • NSOrderedSet -isEqualToOrderedSet:
  • NSSet -isEqualToSet:
  • NSString -isEqualToString:
  • NSTimeZone -isEqualToTimeZone:
  • NSValue -isEqualToValue:

2.3 字符串驻留

字符串驻留的优化技术: 把一个不可变字符串目标的值拷贝给各个不同的指针。

Objective-C 选择器的姓名也是作为驻留字符串储存在一个共享的字符串池傍边的。

NSString *stra = @"Hello";
NSString *strb = @"Hello";
BOOL wt = (stra == strb); // YES

选择器的比较

OBJC_EXPORT BOOL
class_respondsToSelector(Class _Nullable cls, SEL _Nonnull sel) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
- (BOOL)respondsToSelector:(SEL)aSelector;
if([device respondsToSelector:@selector(setSmoothAutoFocusEnabled:)]){
}

III 代码重构(前提是现已完成了基本功能)

开发前:设定开发方案、过程 开发进程中:每一个过程告一段落之后,咱们要暂停,进行代码审阅,有针对性的重构(抽离重复代码,模型和视图各尽职责)

代码重构的原则: 把代码放在它最应该呆的当地

1、运用类办法完成字典实例化模型 (模型,一般是plist文件,网络)

运用类办法实例化模型数组

//类办法可以快速实例化一个目标--把代码放在它最应该呆的当地
+ (instancetype) appInfoWithDictionary : (NSDictionary *) appDictionary;
//回来plist文件对应的模型数组 ,运用懒加载
+ (NSArray *)appList;

2、运用类办法实例化视图目标,并用数据模型安装视图内容

用类办法进行视图的实例化

+ (instancetype) appView;//运用类办法加载xib
+ (instancetype) appViewWithAppInfo:(KNAppInfo *) appInfo;//运用类办法加载xib,参数用于视图的数据安装

see also

更多内容请重视 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究范畴;

iOS小技能:字典转模、对象的相等性