前言

字典转模型

/** 通常实现字典实例化模型,都实现了以下模型的实例化方法*/
//使用字典实例化模型
- (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 代码重构(前提是已经实现了基本功能)

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

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

1、使用类方法实现字典实例化模型 (模型,通常是plist文件,网络)

使用类方法实例化模型数组

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

2、使用类方法实例化视图对象,并用数据模型装配视图内容

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

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

II 字典转模型

  • 使用字典的坏处

​通常取出和修改数据字典的数据,都要通过编写“字符串类型”的key值-》编辑器IDE没有智能提示、手动写key容易写错,且此时IDE不会有任何的警告和报错。​​ 字典的使用例子

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


1)数据模型(专门用来存放数据的对象),使用数据模型表示数据更专业些


2)​​使用模型修改数据、读取数据均采用对象的属性,提高编写效率​

2.1 字典转模型的实现步骤

1)字典转模型的过程,通常被封装在模型内部 2)模型应该提供一个“带有NSDictionary类型”参数的构造方法

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

2.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文件中

III 基础知识

3.1 深复制&浅复制

深复制即内容拷贝


即源对象和副本指向的是不同的两个对象; 源对象的引用计数器不变,副本的引用计算器为1;


指针拷贝(浅复制)


源对象和副本指向同一个对象; 对象的引用计算器+1,相当于做了一次retain操作


3.2 九宫格计算方法

1)每一列的x值一样,x值由列号决定 2)每一行的y值一样,y值由行号决定

//搭建界面,九宫格(以View为单元,内含UILabel、UIButton、UIImageView,同行和同列的位置关系 center.x = x+ width*0.5)

//view 的封装,带有数据模型的构造器以便进行内部控件的数据装配 ;数据模型(plist-》字典-》模型)--自定义的Plist 通常放置于Supporting Files目录中

#define kAppViewWidth 80 //视图宽度

#define KAppViewHeight 90 //视图高度

#define kColumnCount 4 //每行的视图个数--总列数

#define kRowCount 5 // 每一列的视图个数--总行数

//水平间距

CGFloat marginX =(CGRectGetWidth(self.view.frame)- kColumnCount * kAppViewWidth)/(kColumnCount+1);

//垂直间距

CGFloat marginY = (CGRectGetHeight(self.view.frame)- kRowCount* KAppViewHeight)/(kRowCount+1);



for (int i=0; i<28; i++) {

//行号

int row = i/kColumnCount;

//列号

int column =i%kColumnCount;

//位置

CGFloat x=marginX+(marginX+kAppViewWidth)*column;//x值决定视图所在的列;

CGFloat y= marginY+(marginY+KAppViewHeight)*row; //y值决定视图所在的行

//创建视图

UIView *appView = [[UIView alloc]initWithFrame: CGRectMake(x, y, kAppViewWidth, KAppViewHeight)];

[appView setBackgroundColor:[UIColor redColor]];

//将子视图添加至父视图

[self.view addSubview:appView];

}

3.3 内存分析(栈、堆的存储信息)

1、只读指针属性的分析(指向关系不可变,指向对象的内容可变)


不可变属性的值,若存储的是指针,则该属性对应的对象成员是可变的 只读指针属性的地址值不可变,意味的指针和指向的对象间的关系不可变,但被指向的对象内容是可变的


示例1:UIButton 对象有UILabel 、UIImageView 属性,都是readonly


即这两者的属性存储的指针地址是只读的,不可修改


,但只读的指针指向的对象的属性成员是可以修改的

示例2:​​修改UIButton的只读属性titleLabel指针对应的对象属性font​​(readonly表示titleLabel的指针指不可修改,但label的font可以修改)

[[downloadButton titleLabel] setFont: [UIFont systemFontOfSize:12]];
//设置UIButton的title的font,先获取UI Button的内部UILabel:@property (nullable,nonatomic,readonly,strong) UILabel *titleLabel NS_AVAILABLE_IOS(3_0);
//@property(nonatomic,strong) UIFont *font NS_DEPRECATED_IOS(2_0, 3_0) __TVOS_PROHIBITED;过时

示例3:​​a basic type & a class 的声明方式​


a basic type是存储在栈区 class是栈区存储着堆区的对象对应的指针


//Change this:    
CGFloat *marginX =(self.view.bounds.size.width - kColumnCount * kAppViewWidth)/(kColumnCount+1);
//to
CGFloat *marginX =(self.view.bounds.size.width - kColumnCount * kAppViewWidth)/(kColumnCount+1);
//Get rid of the asterisk. CGFloat is not a class, it is a typedef for double (a basic type).

3.4 instancetype简介

OC中,在IOS7之后主推instancetype。 swift语言中,绝大数的类的实例化,也都不需要指定类型。


C++的11版本中,也有类似的关键字auto类型 可见所有的语言都致力于,使语言更容易使用


​instancetype​​ 在类型表示上跟id一样(可以表示任何对象类型)


instancetype 主要用于类方法实例化对象时,让编译器主动推动对象的实际类型,以避免使用ID,造成开发中不必要的麻烦


1.instancetype 只能使用于返回值类型,不能像id一样用于参数类型;但instancetype比id多的一个好处是:


IDE会检查instancetype的真实类型 ,提前警告(Incompatible pointer types initializing 'NSString *' with an expression of type 'KNAppInfo *'),以避免使用ID造成开发中不必要的麻烦


2.Init方法应该遵循Apple生成代码模板的命名规则,返回类型应该使用instancetype而不是id。 当类构造方法被使用时,它应该返回类型是instancetype而不是id。这样确保编译器正确地推断结果类型,可避免运行时才报错。


属性不能使用New 开头进行命名


3.5 @synthesize的用法


@synthesize 中可以定义 与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问(主动指定属性使用的成员变量名称)

@property (nonatomic,strong,readonly) UIImage *image;//存储字典对应的图片对象

//实现文件

#import "KNAppInfo.h"

@implementation KNAppInfo
@synthesize image =_image;//@synthesize 中可以定义 与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问

/**

懒加载模型的图片对象属性
*/
- (UIImage *)image{
if (nil == _image) {//
_image = [UIImage imageNamed:self.icon] ;
}
return _image;
}

3.6 @property

声明property的语法为​​:@property (参数1,参数2) 类型 名字;​


1)参数主要分为三类: 读写属性: (readwrite/readonly 语意:(assign/retain/copy) 原子性: (atomicity/nonatomic)针对多线程问题 2)各参数意义如下:


readwrite: 产生setter\getter方法 readonly: 只产生简单的getter,没有setter。 assign: 默认类型,setter方法直接赋值,而不进行retain操作 retain: setter方法对参数进行release旧值,再retain新值。 copy: setter方法进行Copy操作,与retain一样 nonatomic: 禁止多线程,变量保护,提高性能

​developer.apple.com/library/mac…​

see also

Xcode使用小技巧


 

???? 联系作者: iOS逆向(公号:iosrev)


 ​


???? 简历模板、技术互助。关注我,都给你。

iOS小技能:字典转模、代码重构_类方法