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

目录
  • 前言
  • I 字典转模型
    • 1.1 字典转模型的实现步骤
    • 1.2 字典转模型的过程
  • II 对象的相等性 & 本体性
    • 2.1 相等性检查
    • 2.2 Foundation 框架中,自己实现的相等性检查
    • 2.3 字符串驻留
  • III 代码重构(前提是已经实现了基本功能)
  • see also

前言

字典转模型

/** 通常实现字典实例化模型,都实现了以下模型的实例化方法*/
//使用字典实例化模型
- (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字典转模对象相等性的资料请关注我们其它相关文章!

(0)

相关推荐

  • iOS中使用对象的弱引用示例代码

    简介 我们都知道使用 UIImage imageNamed 创建的 UIImage 对象会被持有(强引用),如果图片太大会占用内存,损耗 APP 的性能,影响用户体验,如果能改造对其的强引用变为弱引用就可以解决问题. 我们可能会有类似上面的场景,有些对象暂时保存起来,可能后面会用到,也有可能不会使用,但是又不想去管理它们的生命周期,如果它们能够自己被销毁就很省事,不需要去关心这些对象到底耗费了多少内存. 今天跟大家聊聊如何在 iOS 开发中保持对对象的弱引用而不是强引用,希望看完之后,能帮助到大

  • iOS调试Block引用对象无法被释放的小技巧分享

    Block技术在iOS开发中非常流行也很方便,但是稍微疏忽就可能会产生引用无法被释放的问题,从而造成内存泄漏.那如何知道哪个Block持有了对象并造成内存泄漏呢? 一个解决的方法是在程序运行时通过Xcode的Debug Memory Graph 来查看当前进程中所有生命周期内的对象.这样可以在调试时通过这个功能发现一些本来应该被释放但是却没有被释放的对象.从而确定哪些对象有内存泄漏的嫌疑. 当点击某个对象时,右边可以看出这个对象的内存分配情况以及被引用的情况,从而可以进一步跟踪确认出对象是被谁持

  • IOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解 在实际的开发需求时,有时候我们需要对某些对象进行打包,最后拼接到参数中 例如,我们把所有的参数字典打包为一个 字符串拼接到参数中 思路:利用系统系统JSON序列化类即可,NSData作为中间桥梁 //1.字典转换为字符串(JSON格式),利用 NSData作为桥梁; NSDictionary *dic = @{@"name":@"Lisi",@"sex":@"m",@"tel&qu

  • iOS关联对象示例详解

    背景 在iOS开发中如果我们想给一个对象动态添加属性或者给category添加属性的时候,都是通过runtime的关联对象去实现,那我们添加的属性到底是如何存取的呢?是直接添加到了对象自身的内存中了去吗?带着这些疑问让我们看一runtime的源码,解开关联对象的神秘面纱. 关联对象源码 存值 void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) { _o

  • 详解iOS应用UI开发中的九宫格坐标计算与字典转换模型

    九宫格坐标计算 一.要求 完成下面的布局 二.分析 寻找左边的规律,每一个uiview的x坐标和y坐标. 三.实现思路 (1)明确每一块用得是什么view (2)明确每个view之间的父子关系,每个视图都只有一个父视图,拥有很多的子视图. (3)可以先尝试逐个的添加格子,最后考虑使用for循环,完成所有uiview的创建 (4)加载app数据,根据数据长度创建对应个数的格子 (5)添加格子内部的子控件 (6)给内部的子控件装配数据 四.代码示例 复制代码 代码如下: // //  YYViewC

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

    目录 前言 I 字典转模型 1.1 字典转模型的实现步骤 1.2 字典转模型的过程 II 对象的相等性 & 本体性 2.1 相等性检查 2.2 Foundation 框架中,自己实现的相等性检查 2.3 字符串驻留 III 代码重构(前提是已经实现了基本功能) see also 前言 字典转模型 /** 通常实现字典实例化模型,都实现了以下模型的实例化方法*/ //使用字典实例化模型 - (instancetype) initWithDictionary :(NSDictionary *) ap

  • 微信小程序事件绑定传参冒泡及捕获的示例详解

    目录 常见的事件有: currentTarget和target的区别 事件传递参数 touches和changedTouches的区别 事件的绑定两种方法 事件传参 事件的冒泡与事件的捕获 小结 常见的事件有: 类型 触发条件 最低版本 touchstart 手指触摸动作开始   touchmove 手指触摸后移动   touchcancel 手指触摸动作被打断,如来电提醒,弹窗   touchend 手指触摸动作结束   tap 手指触摸后马上离开   longpress 手指触摸后,超过35

  • IOS开发之判断两个数组中数据是否相同实例详解

    IOS开发之判断两个数组中数据是否相同实例详解 前言: 工作中遇到的问题,这里记录下,也许能帮助到大家 实例代码: NSArray *array1 = [NSArray arrayWithObjects:@"a", @"b", @"c", nil nil]; NSArray *array2 = [NSArray arrayWithObjects:@"b", @"a", @"c", nil

  • 微信小程序 点击控件后选中其它反选实例详解

    微信小程序 点击控件后选中其它反选实例详解 前言: 如果需要实现进来进行给按钮加上买一送一的样式,或者单击就选中单个按钮,只能靠css结合js进行控制了,小程序暂时没有这样的控件. 实现效果图: 微信小程序进来的时候自动进行按钮样式的初始化,这个需要一个字段做判断,加上正则表达式wxml文件: <block wx:for="{{liuliangItems}}"> <block wx:if="{{item.one2one == 1}}"> &l

  • 微信小程序中使用Promise进行异步流程处理的实例详解

    微信小程序中使用Promise进行异步流程处理的实例详解 我们知道,JavaScript是单进程执行的,同步操作会对程序的执行进行阻塞处理.比如在浏览器页面程序中,如果一段同步的代码需要执行很长时间(比如一个很大的循环操作),则页面会产生卡死的现象. 所以,在JavaScript中,提供了一些异步特性,为程序提供了性能和体验上的益处,比如可以将代码放到setTimeout()中执行:或者在网页中,我们使用Ajax的方式向服务器端做异步数据请求.这些异步的代码不会阻塞当前的界面主进程,界面还是可以

  • 微信小程序 增、删、改、查操作实例详解

    微信小程序 增.删.改.查操作实例详解 1.以收货地址的增删改查为例 2.文件目录 js文件是逻辑控制,主要是它发送请求和接收数据, json 用于此页面局部 配置并且覆盖全局app.json配置, wxss用于页面的样式设置, wxml就是页面,相当于html <form bindsubmit="addSubmit"> <view class="consignee"> <text class="consignee-tit&q

  • 微信小程序中form 表单提交和取值实例详解

    微信小程序中form 表单提交和取值实例详解 我们知道,如果我们直接给 input 添加 bindinput,比如:<input bindinput="onUsernameInput" />,那么可以在 onUsernameInput 中直接使用 e.detail.value,即: onUsernameInput : function(e) { e.detail.value; } 但是,如果有多个输入控件,我们不可能为每个控件添加 bindinput.bindchange

  • 小程序:授权、登录、session_key、unionId的详解

    微信应用的一个很大的优势就在于使用过程中是不需要进行注册和显式登录的,大部分问题基本上可以一键解决.但是在授权.登录和获取用户信息的过程中都发生了哪些事情,今天我们就来讨论一下.这篇文章主要分析以下几个问题: 授权和登录的意义 session_key 的作用 unionId 的作用,有哪些获取途径 在应用中如何保存用户登录态 1. 授权和登录的意义 首先必须要明白,授权和登录实际上是两个操作. 1.1 授权(已废弃) 那授权的作用是啥呢?从小程序官方文档中我们可以看到授权操作只需通过wx.aut

  • uni-app微信小程序登录并使用vuex存储登录状态的思路详解

    微信小程序注册登录思路 (这是根据自身的项目的思路,不一定每个项目都适用) 1.制作授权登录框,引导用户点击按钮 2.uni.login获取code 3.把code传给后端接口,后端返回如下数据 openid: "ogtVM5RWdfadfasdfadfadV5s" status: 1 // 状态码:status==0(该用户未注册,需调用注册接口) status==1(该用户已注册) 4.判断用户是否注册,并调用用户信息接口 (1)若已注册则提示登录成功,并调用后台给的获取用户信息的

  • 微信小程序开发数据缓存基础知识辨析及运用实例详解

    提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容. 提示:以下是本篇文章正文内容,下面案例可供参考 一.微信数据缓存是什么? 在实际开发中,在用到一个数据时,我们需要调用api接口去得到,然后渲染在页面中,但是对于一些数据,是经常需要使用的,如果每次使用时都需要调用api接口,会十分麻烦.数据缓存就解决了这个问题,我们可以在初次调用某api得到数据的同时将数据缓存,那么在之后的使用过程

随机推荐