一、点按钮,弹出的这个效果,这实际上是个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方法,
一个是对象方法,一个是类方法,
这个是必备的,这是一套,以后大家写模型的时候,必须把这两个方法封装进去,
好了,这是我们字典转模型,给大家说的,
原文地址:https://blog.csdn.net/madoca/article/details/129072960
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_39686.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。