【字典转模型 Objective-C语言】

一、点按钮,弹出的这个效果,这实际上是个Label,

这是一个标签

这实际上是一个Label,点按钮弹出的这个效果,

设置一个Label的背景色、前景色、透明度、等等,

让它加进来,然后通过动画让它隐藏掉,

这就是,这个效果的实现思路,

咱们这个效果,先稍微往后放一放,

这个并不是重点,

接下来要做的一些东西,如果对于初学者来说,是有一些难度的,

那么这些难,难在哪儿了呢,

我们这里要做的是个什么功能呢,

要做的是,把刚才这个九宫格这个代码,刚才已经把它该做的已经做完了,

我们要做的是,把刚才这些代码封装一下,

封装,使用一个叫xib的东西,“叉爱必”的东西,

然后,同时,我们还要把这些代码做一些其他的封装,

就是做一系列的封装,

我们接下来写这些代码,写完以后这个效果还是这个效果,

只不过代码,要比之前看起来要好,

代码,做了更高级的封装处理,

这就是我们接下来要做的一系列的操作,

2.我们先来看一下我们这个代码,

我们这里是在viewDidLoad,当我们的控制器的view加载完毕以后,里面通过这一系列的内容,里面写一个循环,循环里面创建view,设置view的一些坐标,创建子控件,加到view里面,设置子控件的坐标、属性、数据,一个一个子控件设置,是不是在这个for循环里面有这么一堆的代码啊,

这么一堆的代码,写到for循环里面,大家觉得好不好,

觉得不爽对吧,

哪里不爽,有些同学说性能低,其实性能一点儿都不低,运行起来性能一点儿都不低,

对,可扩展性不强,

哪儿可扩展性不强,为什么可扩展性不强,

有同学说,再加一个按钮,那我直接把它改一下不就行了吗,我们数据里面,有几个数据啊,

数组里面,有几个数据啊,

现在我们数组里面,是不是有这么12条吧,

选中app.plist文件最后一个Dictionary,command + C、command + V,然后再运行,是不是又多出来一个按钮啊,

这个代码是有问题,问题也就是可扩展性的问题,

那么可扩展性,指什么问题,

其实这个代码,关键点在哪儿,关键点是这个代码没有达到我们的“可重用”,

没有达到“可重用”,

比如说,现在你这个控制器里面需要显示一个九宫格,是不是这一堆代码,

我又建了一个新的一个控制器,这个控制器里面,也要显示这么一系列的九宫格,这个时候怎么办,所有代码command + C、command + V,是不是直接拷过去,改一改,

是不是得这么做啊,

这叫代码的复制、粘贴,这叫代码的重用吗,不叫,

我们要想实现的是,当另外的一个控制器里面,也要显示九宫格的时候,直接把你这个类拿过来,直接就能用,

直接把你这个模块拿过来,调里面的某个方法,直接就能显示九宫格了,

是不是不需要把这个九宫格的代码从头儿再写一遍啊,

这就是这个代码的可重用性不强,换句话说,这个代码只能依赖于这个程序,

所以说,我们能不能把这个代码给它提取出来呢,所以,接下来,我们就说一下思路,怎么来提取这个代码:

二、提取这个九宫格代码:

1.告诉大家一个新的东西,就是xib文件,接下来,先告诉大家,这个xib是干什么的,

刚才大家有没有发现,每次创建一个控件,都要写这么一堆代码,

这样太繁琐了,我们要实现的效果是“所见即所得”,能不能实现这个效果,刚才我们发现,每一个应用是不是长的都是一样的啊,能不能在一个storyboard里先写把这3个控件(图片框、标签、按钮)拖出来,设置好坐标,然后呢,你把这个应用分别加载12次就ok了,

每一个应用的内容都是一样的,这些代码,我们通过可视化的方式,拖拉拽直接生成了,这样的话,就省的我去写代码了,

就是我想通过拖拉拽来生成这个控件,不需要去写代码了,

因为在一开始做iOS开发,所有的这些都要通过代码来实现,但是后来,为了提高开发效率,苹果就出了一个叫xib的东西,再后来,就又帮我们出了一个storyboard,

storyboard,我们已经用过了吧,就是往里面去拖拉拽控件,这个效果吧,

也就是说,一开始有了xib,后面有了storyboard,

这两个东西产生的原因,就是为了一点:“提高我们的开发效率”,

你那些控件,不需要每次都通过代码来创建了,可以通过storyboard,xib,快速通过鼠标拖拉拽生成的,生成以后你就可以直接用这个东西了,

2.那么有人可能会问,storyboard、xib,这两个东西都是为了提高开发效率,都是通过拖拉拽生成控件,

换句话说,它们两个都是用来描述软件界面的,

软件界面长什么样儿,就是通过这两个东西描述,

你把控件拽上来,它会根据你这个界面,根据这个storyboard文件,或者根据你这个xib文件,后台会自动生成这些代码,后台也是通过代码实现的,

就不需要我们来写了,对吧,

那么既然它们俩个都是做这件事情的,那么它们俩个有什么区别呢,

注意,这个xib,它是一个轻量级的描述软件界面的文件,

这个storyboard,它是一个重量级的描述软件界面的文件,

什么是重量级、什么是轻量级的呢,

轻量级的xib,它是用来描述一些,比如说一个控制器局部的小View,

比如说,这个九宫格中,每个应用,是整个页面中这么一小块儿吧,这么一小块儿内容,可以使用xib,

比如说,我们要描述一个多个界面,多个界面是不是意味着有多个控制器啊,

从这个界面,一点就到另一个界面,再一点又到另外一个界面,

当你要描述多个界面的时候,多个控制器,以及每个界面的界面之间,还有什么关系,这种情况下,使用后面这个重量级的storyboard,来进行描述,

现在我们是要描述一个一个的屏幕界面吗,是要描述一个一个的手机界面吗,不是,

是不是只要描述一个界面里面的某一个内容吧,

这个时候就可以使用xib,

所以说,接下来我们用的时候,就通过这个xib来描述我们这么一个界面,

3.接下来,我们就要给大家介绍这么几个知识,一个就是我们这个xib,

使用xib精简代码:

1)什么是xib,xib能做什么,

用来描述软件界面的文件,

如果没有xib,所有的界面都需要通过代码来手动创建,

有了xib以后,可以在xib中进行可视化开发,然后加载xib文件的时候,系统自动生成对应的代码来创建界面,

与xib类似的还有storyboard文件,

2)xib与storyboard既然都是描述软件界面的,有什么区别吗,

xib是轻量级的,一般只用来描述一个界面中的某部分内容(用来描述局部UI界面)

storyboard是重量级的,一般用来描述软件的多个界面,以及不同界面之间的转换关系,换句话说,就是这个里面可以有多个控制器,并且还可以描述每个界面与每个界面之间的关系,跳转关系,

3)加载xib的方式:

NSBundle *bundle = [NSBundle mainBundle];

[bundle loadNibNamed];

[bundle bundlePath]; 查看mainBundle的路径,

4)查找xib在手机模拟器中的位置,安装到手机上后就变成了nib文件了,

/user/Steve/Library/Developer/CoreSimulator/Devices/0C63A035-071E-4EFC-8717-C387A3F7E026/data/Containers,

NSString *home = NSHomeDirectory();

NSLog(@“%@”,home);

5)大家要清楚,无论是xib还是storyboard,这两个东西,最终都是生成代码的,

也就是说,最后还会生成一个一个创建代码,

创建控件那个代码,只不过这个代码不需要我们手动来写了,

在我们继续介绍xib和storyboard之前,给大家介绍一个相对简单的东西,

先把这个搞定以后,然后咱们就来开始说这个xib,用这个xib,来封装我们的界面,

好,接下来给大家说的是一个什么东西呢,就是我们这里列出来的,这个叫做“字典转模型”,

三、字典转模型,

1.先把这个说出来,这个是和我们的数据有关的,

为什么要把字典转成模型,

字典的缺陷:

1)“键”是字符串,如果写错了,编译器不报错(在编译的时候不报错),运行时可能出错,出错了很难找错,

2)使用“模型”可以更方便的使用面向对象的3大特性(封装、继承、多态)进行扩展,

3)什么是“模型”,模型就是自定义的类,通过为“类”增加各种属性来保存数据

4)字典转模型要修改哪里的代码,

- 创建一个模型类,

- 在懒加载的时候,把加载到的数据都放到模型类中,然后再把模型对象放到数组中,

复习:把app.plist转换成模型数组的过程,参考“字典转模型的过程”

把字典转模型的过程封装到“模型”内部,

原因:将来的这个“模型”可能会在很多地方被用到(比如有很多个控制器都会使用这个模型),那么每次用到模型的地方都需要写一次把字典中的数据赋

思路:

1)在模型中接受一个NSDictionary的参数,然后在模型内部把NSDictionary中的数据赋值给模型的属性,

2)封装一个initWithDict方法和一个appWithDict方法,

3.好,接下来我们就说一下这个“字典转模型”,这个是与咱们数据有关的,把这个说完以后,紧接着,就给大家说我们这个xib,

4.好,我说一下这个字典转模型,是个什么东西,

首先,大家想想,刚才咱们的程序中,哪里用到了字典,

是不是懒加载app.plist的时候,这里用到了字典了吧,

- (NSArray *)apps{

if(_apps == nil){

//加载数据

//1.获取app.plist文件在手机上的路径

NSString *path = [[NSBundle mainBundle] pathForResource:@“app.plist” ofType:nil];

//2.根据路径加载数据,

_apps = [NSArray arrayWithContentsOfFile:path];

}

return _apps;

}

我们把那些数据加载起来以后,这个apps数组里面,保存的就是字典了吧,

一个应用,对应的是不是就是一个字典数据,

那么接下来我们这里所说的“字典转模型”的意思,就是说,

把这个数组中,每一个字典,转成一个模型,

那么这个时候,大家可能会问,模型是什么,

首先,我们说,这个数组当中,存一个数据,用的是一个字典吧,

这个字典在这里的作用,就是为了,保存数据,

这个数组中的字典的作用,是不是就是为了保存数据,

字典里面有键值对,键值对,键对应的值,就是数据,

每一个键和值,也就是说,一个字典里面,可以有很多个键值对,是不是可以保存很多个数据吧,

比如说,你要描述一个人的信息,包含姓名、性别、年龄、身高、体重,一堆数据,这一堆数据怎么来存储,创建一个字典对象,在这个字典对象中,创建很多个键值对,

是不是就可以保存这个人的所有的数据了,

也就是说,字典,就是用来保存数据的,

那么我们这里要做的是,把字典转成模型,

这个模型的作用也是保存数据的,

那么什么是模型呢,

或者说,字典可以保存数据,模型怎么来保存数据呢,

比如说,一个字典中,有三个键值对,

姓名、性别、身高,

这是不是字典中的三个键值对啊,

意味着,这个字典中,保存着这3个数据吧,

那么,接下来,我想用另外一种方式来保存这个数据,

怎么保存呢,我可以这么做,

我可以新建一个Person类,Person里面有几个属性呢,

3个属性,这3个属性分别就是:姓名、性别、身高,

然后呢,我创建一个Person类的一个对象,

然后呢,为这个对象的这三个属性,name赋一个值,就是字典中键值对中的那个name键,对应的数据,

为这个Person对象的age属性,赋一个值,

为这个Person对象的height属性,赋一个值,

这3个值的来源,分别就是字典中的那3个键值对,的来源,

那3个键对应的值,来赋值,

那么这样的话,那个Person对象,这个就是个模型,

也就是说,你要存储一些数据,可以通过一个字典的方式,键值对的方式来存储,

也可以新建一个类,这个类中呢,有几个属性,就是字典中有几个键,就给它写几个属性,

然后呢,创建一个这个类的对象,然后把字典中键值对的值,分别设置给这个对象的每一个属性,这样的话,用一个这个对象,也可以表示一条数据,

和字典是不是一样的啊,

也就是说,这里接下来要给大家说的“字典转模型”的意思,就是说,把现在是用字典来存储数据,然后把这个字典,替换成一个一个的类的对象,用类的对象来保存数据,

明白我想干什么了吧,

3.然后大家想一想为什么要样做,这样做有什么好处,

等我们写完以后,看看到底有什么好处,

注意,以后的开发,都是用模型,不会用字典的,

所以说,这个你必须得掌握,

得熟练掌握,

我不相信你以后不会掌握,因为这个东西写的太多了,就好比说,你小的时候,你担心你长大了以后不会走路吗,

今天,先明白这个“字典转模型”的含义,是不是把一个字典,用一个类的对象来保存啊,把字典中的数据,不用字典来保存了,用一个类的对象来保存,

那么,它也是用来存数据的,

好,咱们先把这个实现了,

4.注意,我们现在既然要用一个类来表示一个字典中的数据,

那么,首先要怎么样,

首先要建一个类,

右键-〉New File -〉选中上面的iOS-〉选中Cocoa Touch Class -〉回车 -〉这个类叫什么啊,

注意,我们现在一个字典中,保存的是不是一个应用的数据,一个应用就是一个app,所以,我们这个模型,也可以把它叫做app,加个Test前缀,就叫TestApp类吧,

这个模型就继承自NSObject类,

然后呢,回车,

然后,接下来,我的问题是,这个类中有几个属性,

这个类中有几个属性,取决于当前你每个字典中有几个键值对,

每个字典中,是不是有两个键值对,

一个是name,一个是icon,

所以说,这个模型的属性,是不是也有两个啊,

这么模型中的属性的名字,建议一定要和字典中的键的名字是一样的,

字典中这个键叫name,这个模型中的属性也叫name,

字典中这个键叫icon,这个模型中的属性也叫icon,

当然你说我就写的不一样行不行,不一样也行,但是后面可能你就遇到麻烦了,

所以说,最好是起的一样,

所以说,现在我们就通过分析发现,这个模型中应该有几个属性啊,两个,第一个属性叫name,什么类型的,NSString类型,第二个属性叫icon,什么类型的,NSString类型,

所以说,模型会写了吗,

#import <Foundation/Foundation.h>

@interface TestApp:NSObject

@property(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *icon;

@end

既然是NSString类型,对,所以说这儿用什么,用copy,

好,这两个属性是不是写好了,

到此为止,我们模型先写这么多,现在这个模型里面是不是有两个属性了,

可以用这个模型来保存数据了吧,

那么,接下来,注意看,现在我们在懒加载的时候,加载完毕,这个数组里面,是不是就是一个一个的字典,

我希望这个懒加载加载完毕以后,这个数组里面是一个一个的模型,

所以说,你这里能直接把它赋值给这个数组吗:

_apps = [NSArray arrayWithContentsOfFile:path];

你直接把它这个结果赋值给这个数组,这个数组里面,就变成一个一个的字典了吧,

所以说,我这里要先把这个字典的数据,是不是转成一个模型的数据以后,然后再赋值给这个_apps,

所以说,怎么做,注意看,我要改一下这个代码了,

我们现在这个模型是不是建好了,

在TestApp.h文件中:

#import <Foundation/Foundation.h>

@interface TestApp : NSObject

@property(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *icon;

@end

在TestApp.m文件中:

#import “TestApp.h”

@implementation TestApp

@end

在ViewController.m文件中:

#import “ViewController.h”

@interface ViewController ()

//1.加载app.plist的属性

@property(nonatomic,copy)NSArray *apps;

@end

@implementation ViewController

//2.重写apps的getter方法,懒加载数组

- (NSArray *)apps

{

if(_apps == nil){

NSString *path = [[NSBundle mainBundle] pathForResource:@“app.plist” ofType:nil];

_apps = [NSArray arrayWithContentsOfFile:path];

}

return _apps;

}

模型建好了以后,我们在这里的代码就要实现,把这个数据转成模型,

注意,我先把这个数据加载起来,

加载起来以后,给它赋值给一个NSArray,

//1.加载数据,获取app.plist文件在手机上的路径

NSString *path = [[NSBundle mainBundle] pathForResource:@“app.plist” ofType:nil];

//2.根据路径加载数据

NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];

//arrayDict,为什么叫arrayDict,因为我们这个数组里面存的都是一个一个字典吧,

//然后,我要把一个一个的字典,转成一个一个的对象,放到另外一个数组里面,

//那么,既然要放到另外一个数组里面,是不是要向另外一个数组中一个一个的加对象啊,

//所以说,另外一个数组就应该是一个什么,NSMutableArray吧,

//应该是一个可变数组吧,

//3.创建一个可变数组,用来保存一个一个的模型对象,

//NSMutableArray arrayModels,里面是不是要用来保存一个一个的模型,

//模型,我们就管它叫做Model,Models,

//既然是一个可变数组,我们要用NSMutableArray,

//一个空的可变数组,

NSMutableArray *arrayModels = [NSMutableArray array];

//这,就表示创建了一个空的一个可变数组,

//创建好空的可变数组以后,接下来要做的就是干什么呢,循环这个字典数组,arrayDict,把里面的每一个字典,创建一个对象,然后把这个对象,加到这个可变数组里面,

//4.循环字典数组,把每个字典对象转换成一个模型对象,

//因为我们这是一个数组,所以我们可以使用for循环,也可以使用for - in 循环吧,

//这里大家喜欢用哪个,还是for - in ,吧,for - in 相对来说更简单一些,

for (type *object in collection){

statements

}

//因为这个数组当中,arrayDict,每一个元素就是一个字典,所以说,我们这里面,可以设置一个什么,NSDictionary *dict,

//然后,这里来一个arrayDict,

for ( NSDictionary *dict in arrayDict){

statement

}

//这样的话,就表示循环这个字典数组,把里面的每一个字典,是不是赋值给这个字典变量*dict,

//这样的话,这个dict是不是就是数组里面的每一个字典对象,

//拿到这个字典对象以后,接下来,每次遇到一个字典对象,就要创建一个模型,

//创建一个模型,

//这个模型是不是就是我们刚才说的TestApp这个模型啊,

//但是在这个地方,我们写TestApp,能访问到吗,根本访问不到,

//原因是这里没有引入头文件,TestApp.h,

//在最前面写上#import “TestApp.h”,引入TestApp的头文件,

//这样的话,把这个头文件导入,这里就循环这个字典数组里面的每一个字典,每一个字典对应的创建一个模型对象,

for (NSDictionary *dict in arrayDict) {

//创建一个模型

TestApp *model = [[TestApp alloc] init];

//好,这样就创建好了这个模型,创建好这个模型以后,这个模型里面对应的那个属性,有数据吗,这个模型是不是空的啊,

//model.name = 是不是要把字典中的name赋值给它,怎么写:

model.name = dict[@“name”];

//字典中的name,是不是要赋值给这个模型,

//字典中的icon,是不是也要赋值给这个模型,

model.icon = dict[@“icon”];

//这样的话,这个模型里面,是不是就有这两个数据了,模型里面,就有这两个属性了,

//然后,把这个模型怎么样,加到哪里,是不是加到可变数组里面,

//把模型加到arrayModels中,

[arrayModels addObject:model];

//这样的话,就把字典加到这个模型里面了,也就意味着,当这个for循环执行完毕以后,这个arrayModels,这个集合里面,是不是就已经保存了所有的模型对象了吧,

//然后,我们直接让这个下划线apps等于这个arrayModels,_apps = arrayModels,

_apps = arrayModels;

//这样的话,当这个if语句执行完毕,这个apps里面,是不是有了所有的这些模型对象了吧,

//然后,接下来,你再通过索引,拿到这个apps数组里面的任何一个对象,它还是一个Dictionary吗,不是了吧,里面每一个都变成什么,都变成模型了吧,

5.修改原来的代码:

然后,请问大家,我这里的代码是不是需要改一改了:

- (void)viewDidLoad{

[super viewDidLoad];

int columns = 3;

CGFloat viewWidth = self.view.frame.size.width;

CGFloat appW = 75;

CGFloat appH = 90;

CGFloat marginTop = 30;

CGFloat marginX = (viewWidth - columns * appW ) / (columns + 1);

CGFloat marginY = marginX;

for(int i=0;i<self.apps.count;i++){

NSDictionary *appDict = self.apps[i];

//我这个循环里面,这里的代码是不是需要改一改了,

//这是不是一个数组,根据索引拿到数组里面每一个内容,还是字典吗,变成模型了吧,变成TestApp了,

TestApp *appModel = self.apps[i];

//变成模型了以后,紧接着,下面的代码是不是也得改啊:

//来,看看哪儿用到这个模型了,

//设置图片框的数据:

imgViewIcon.image = [UIImage imageNamed:appDict[@“icon”]]);

//这儿,它既然不是字典,这儿是不是应该改成模型,字典是不是才根据键来取呢,模型这儿应该怎么写:

//直接appModel.icon,

//是不是直接这么写啊:

imgViewIcon.image = [UIImage imageNamed:appModel.icon];

//大家想一想,你这么写,appModel.icon,和这么写,appDict[@“icon”],有什么区别吗,

//第一,你通过字典去写的时候,appDict[@“icon”],这个icon是不是没有提示啊,你是不是得手动去写啊,

//而你通过模型去写的时候,appModel.icon,这里是不是有提示,

//第二,有很多同学,自己去写这个字典里的字符串键的时候,有很多时候会把这个写错,icon,这个会写成ioco,什么的,

//这样的话,你写错以后,编译会有提示吗,不会,

//编译根本没有错误提示,只有运行时候,才会因为没有这个键,才会出现意想不到的错误,

//所以,变成模型的好处,第一:会有这个提示,第二:你这个地方,如果写错的话,你编译的时候,就会有错误提示了,比如,写错了,写成appModel.iocc,这样编译时就会把错误给检查出来了,是不是尽量降低我们程序运行的时候出现的错误吧,这是第二,

imgViewIcon.image = [UIImage imageNamed:appModel.icon];

//第三,当你使用模型的时候,将来如果使用多个模型的时候,这个模型因为它是类嘛,就可以使用我们面向对象的继承、封装、多态了,

//是不是可以使用其他的一些面向对象的特性啊,

//例如,这个模型是这样的:

#import <Foundation/Foundation.h>

@interface TestApp:NSObject

@property(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *icon;

@end

//你可以把这个东西,自己再给它扩展,再继承,再给它封装,再给它多态,可以使用其他一些面向对象的特性啊,

//但是用字典的话,不行,它仅仅是一个保存数据的工具,

//所以说,字典转模型的好处:

//第一,就是写代码的时候,有属性的提示,

//第二,在编译的时候,如果写错了,会有错误提示,就会有编译错误,尽量减少运行时错误吧,

//第三,使用模型,可以使用面向对象的各种各样的特征,可以让我们的程序变得更灵活,

//这就是我们字典转模型的好处,

//字典的缺陷,就是:

//1)“键”是字符串,如果写错了,编译时不会报错,运行时会出现各种意想不到的错误,

//2)使用“模型”,可以更方便的使用面向对象的3大特性(封装、继承、多态),进行扩展,

//3)写代码的时候,字典的“键”,没有智能提示,但是模型的属性可以有智能提示,

//这些都是它的一些好处,这些就是字典转模型的好处,

//第一,就是有智能提示,

//第二,就是编译时提示错误,

//第三,就是可以使用面向对象的特性,

//好了,我们接着来改代码吧,既然我们循环里面,获取到每一个数据的模型了,

TestApp *appModel = self.apps[i];

//这儿用模型的icon,

imgViewIcon.image = [UIImage imageNamed:appModel.icon];

//这儿也要把键改一下啊,

//设置Label的数据(标题)

lblName.text = appDict[@“name”];

//改成什么,模型.name,

lblName.text = appModel.name;

//还有哪儿,是不是没了,没了,就改了两个地方吧,

//是不是这儿改了一个name,这儿改了一个icon吧,

//我们再运行一下,command + R,是不是效果还是一样的啊,

//ok,这就是我们这里这个字典转模型,大家明白字典转模型的意义了吗,

//好,接下来,我们继续完善这个字典转模型,这个字典转模型还没完,

三、完善字典转模型,

1.刚才这么写没问题,但是这么写并不好,一般情况下,我们先说哪儿不好吧,

你这么转成模型,是没问题,但是,假如说我有10个地方都在用你这个模型,也就意味着,是不是有10个地方都在用这个字典转模型啊,

- (NSArray *)apps{

if(_apps == nil){

//加载数据

//1.获取app.plist文件在手机上的路径

NSString *path = [[NSBundle mainBundle] pathForResource:@“app.plist” ofType:nil];

//2.根据路径加载数据,

NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];

//3.创建一个可变数组用来保存一个一个的模型对象,

NSMutableArray *arrayModels = [NSMutableArray array];//一个空的可变数组

//4.循环字典数组,把每个字典对象转换成一个模型对象,

for(NSDictionary *dict in arrayDict){

//创建一个模型,

TestApp *model = [[TestApp alloc] init];

model.name = dict[@“name”];

model.icon = dict[@"icon];

//把模型加到arrayModels中

[arrayModels addObject:model];

}

_apps = arrayModels;

}

return _apps;

}

你这么转成模型,是没问题,但是,假如说我有10个地方都在用你这个模型,也就意味着,是不是有10个地方都在用这个字典转模型啊,是不是都要这样转一下,这样的话,你有10个地方都要去这么写,

每一个地方转模型的时候,是不是都要创建一个模型对象,把字典中的每一个键取出来,然后再设置给模型中的每一个属性吧,

是不是每一个地方都得这么写,那么大家想一下,我这个字典中,如果有10个键呢,有10个键值对呢,

这儿怎么办:

TestApp *model = [[TestApp alloc] init];

model.name = dict[@“name”];

model.icon = dict[@“icon”];

是不是写10次啊,

有100个呢,写100次吧,

大家觉得这是问题吗,

你写这个模型类,是不是不光是你自己用,将来也要有其他人要用吧,

你写这个模型,导致团队中其他人用这个模型的时候,都得把字典中的键,一个一个赋值给模型中的属性,

也就意味着,它有100个键值对,我用这个模型的时候,我得赋值100次啊,

怎么样在工作中,做一个让别人都受欢迎的同事呢,

不要给别人造成麻烦,这是最基本的,你这个工作如果总给别人造成麻烦,别人会喜欢你吗,

你如果写模型,想咱们刚才那样写,凡是用到这个模型的人,都得有多少个键值对,依次得赋值很多次啊,

你代码写完之后,应该想一想,这个代码别人用起来方便吗,如果不方便,能不能再封装一下呢,

这样的话,也就是说,我们要把这一块儿代码优化一下,不希望凡是用到我们这个模型的人,都要写很多遍赋值语句吧,

TestApp *model = [[TestApp alloc] init];

model.name = dict[@“name”];

model.icon = dict[@“icon”];

接下来,怎么改这儿,注意看:

我希望这个模型,有一个方法,initWithDict,把这个字典传进来,

TestApp *model = [[TestApp alloc] initWithDict:dict];

我希望我就这么一句话,把这个字典传给你这个模型,你模型的内部,去把这个字典里面的每一个键取出来,赋值给你这个模型的属性,

因为,模型中有多少属性,我知道吗,别人知道吗,别人也不需要知道,

模型里面有几个属性,是不是写模型的人最清楚了,

字典里面有几个属性,把字典给你,你内部去解析字典中的数据,依次赋值给你,模型里面的属性,

而我用的时候,对于我来说,我要用这个模型,我只需要创建一个模型对象,给你一个字典,然后你这个模型,就是一个充满数据的一个模型了,

我是不是就可以拿来用了,

这样的话,对于使用者来说,是不是非常非常的方便吧,

所以说,我就希望,你这个模型里面有一个initWithDictionary,这个方法,

别人只要给你一个字典,你内部会把字典解析,之后赋值给模型,

然后呢,我希望你还有另外一个方法,或许我不想这么做,这样做,还是麻烦,

我希望你有这么一个方法:

TestApp *model = 类方法,

TestApp *model = [TestApp 类方法,

来,总结一下,

1)NSString,它的类方法一般叫什么,stringWith什么什么吧,

这是它的类方法吧,

2)NSArray,它的类方法一般叫什么,

arrayWith什么什么吧,

3)TestApp,它的类方法一般叫什么,

appWith什么什么吧,

那个Test就没有了,NSString,那个NS是不是去掉了,NSArray,那个NS是不是也去掉了,

NSString,它的类方法叫什么,stringWith,是不是前面的前缀去掉了吧,

NSArray,它的类方法叫什么,arrayWith,是不是前面的前缀去掉了吧,

那我们TestApp,它的类方法叫什么,appWith,是不是也是把前缀去掉了吧,

那么,也就是说,我们起名的时候,我就不这么起名,我起个别的名儿行不行啊,行,是行的,但是你起这个名儿以后,你团队开发的时候,大家都是这个习惯,突然你习惯变了,是不是对谁都不好吧,

就是说,你既然就是在这个团队里面,你开发的时候,就遵守大家这个约定,这样的话,你开发的时候,会省事省力,听说过一句话,叫做“约定大于配置”吗,之前可能有同学是做Java开发,Java开发里,是不是到处都是配置啊,一堆繁琐的配置,有人说,很灵活,但是也有人说,很不爽,在.Net里面,配置没有Java那么多,.Net里面,都是叫“约定”,约定好我们都这么做,这就叫“约定”,约定大于配置,我们都约定好这么做以后,开发起来,就非常省事儿,非常快捷,省了很多很多配置,所以有句话叫做“约定大于配置”,苹果里面也是,我们有很多约定,这么约定,约定好以后,就这么做,这样的话,你如果不遵守这个约定,你会发现,各种各样的不爽,你遵守了这个约定,大家都爽了吧,大家好,才是真的好,

所以,我们这里,类方法的起名规则就是,把前缀去掉,把后面内容,app,加一个With什么什么,

TestApp *model = [TestApp appWithDict:dict];

//然后,把字典传进来,

//也就是说,我希望,你这个写模型的人,将来提供两个方法给我用,

//1)一个是initWithDict,

//2)一个是appWithDict,

//将来我用的时候,只要调这两个方法,是不是就把字典传进去,内部你就帮我赋值了,是不是后面就不需要这么写了:

//model.name = dict[@“name”];

//model.icon = dict[@“icon”];

//所以说,大家觉得,现在我们应该改造哪个类啊,是不是应该改造这个模型类TestApp,啊,

//ok,给大家写两个方法,

在TestApp.h文件中:

#import <Foundation/Foundation.h>

@interface TestApp:NSObject

@property(nonatomic,copy)NSString *name;

@property(nonatomic,copy)NSString *icon;

//给大家写两个方法,

//1)一个,这个initWithDict,是一个对象方法,

//用在TestApp *model = [[TestApp alloc] initWithDict:dict];

//2)一个,这个appWithDict,是一个类方法,

//用在TestApp *model = [TestApp appWithDict:dict];

//返回类型,这儿该写个啥啊,我们是不是返回的这个类型啊,TestApp类型吧,我们先写这个,回头再给大家优化,

- (TestApp *)initWithDict:(NSDictionary *)dict;

+ (TestApp *)appWithDict:(NSDictionary *)dict;

//好,这样的话,是不是这两个方法有了,

//你为什么这儿要写这个类型呢,TestApp *,

//因为你看到它,最终是不是返回的就是这个类型自己啊,

//所以说,我们这里就要返回这个类型啊,

//好,实现一下这两个方法,

//在TestApp.m文件中:

#import “TestApp.h”

@implementation TestApp

- (TestApp *)initWithDict:(NSDictionary *)dict{

//在这里面,怎么写,

//这个以前学过吗,首先判断if(self = [super init]){statement},调父类的init方法,是不是先把这个对象初始化一下,

//我们说,在对象方法里面,self,是不是就表示当前对象自己啊,

//因为这个类,是不是继承自Object那个类啊,

//它是有父类的,先调这个父类的init方法,先把这个父类的成员都初始化完毕以后,赋值给这个self,然后接下来在这里,直接再return这个self,

if(self = [super init]{

statement

}

return self;

}

//然后,在这个里面,为这个self的属性是不是赋值,

if(self = [super init]){

self.name = dict[@“name”];

//self.name,字典里面怎么样,字典里面是不是取出这个name属性,

self.icon = dict[@“icon”];

//self.icon,字典里面怎么样,字典里面是不是取出这个icon属性,

}

return self;

}

//这样的话,我们自己定义了一个新的initWithDict这个方法,在这个方法中,当这个对象初始化完毕以后,self = [super init]完毕以后,然后再把这个对象里面的这两个我们自己加的属性再初始化一次,

//然后,接下来,当用户调完这个方法以后,返回了一个self,是不是就是一个已经充满数据的一个对象,

//然后再实现这个类方法,

+ (TestApp *)appWithDict:(NSDictionary *)dict{

//在这里面咋写,

return [self alloc] initWithDict:dict];

}

//是不是ok了,

//好,这是我们这两个,把这两个ok以后,我们这个模型这两个方法就写好了,

@end

然后,在这里,我们这么一句话,是不是就搞定了:

TestApp *model = [TestApp appWithDict:dict];

//是不是只要这么一句话,就把字典转换成模型了,

//字典转模型,就一句话,

//运行一下,可以了吧,

//注意:以后大家写模型的时候,以后再写模型的时候,

1)第一,先把模型里面的属性写好,

2)第二,必须必须封装这两个方法,

如果不封装这两个方法,你这个模型,就是一个不合格的模型,

模型里面必备的,就是属性,以及initWithDict方法,和一个appWithDict方法,

一个是对象方法,一个是类方法,

这个是必备的,这是一套,以后大家写模型的时候,必须把这两个方法封装进去,

好了,这是我们字典转模型,给大家说的,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风清晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值