iOS小技能之字典转模及对象相等性示例详解

来自:网络
时间:2023-07-25
阅读:
目录

前言

字典转模型

/** 通常实现字典实例化模型,都实现了以下模型的实例化方法*/
//使用字典实例化模型
- (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 对象的相等性 & 本体性

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

当两个物体有一系列相同的可观测的属性时,两个物体可能是互相相等 。

2.1 相等性检查

对象相等性检查的主要应用场景:确定一个对象是不是一个集合的成员,对于 NSArray,NSDictionary 和 NSString 容器类来说,更加有用的是进行相等性检查,即对于集合中的每个成员进行判断,因此我们需要重写isEqual: 。

重写 isEqual:

  • 先进行本体性检查,如果失败,就进行实际内容(意义)上的比较,比如判断其中几个主要特性的属性。
- (BOOL)isEqual:(id)object {
  if (self == object) {
    return YES;
  }
  if (![object isKindOfClass:[Person class]]) {
    return NO;
  }
  return [self isEqualToPerson:(Person *)object];//关键属性的判断,比如身份证ID
}
  • 重写 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小技能之字典转模及对象相等性示例详解

以上就是iOS小技能之字典转模及对象相等性示例详解的详细内容,更多关于iOS字典转模对象相等性的资料请关注其它相关文章!

返回顶部
顶部