【iOS开发-48】九宫格布局案例:自己主动布局、字典转模型运用、id和instancetype差别、xib反复视图运用及与nib关系
本次九宫格案例:
(1)导入app.plist和各种图片素材,方便兴许开发。实际开发中,也是如此。
(2)把plist中数组导入进来。
——由于本案例中app.plist终于是一个数组,数组里面是字典。所以我们须要一个数组类型来接受这个plist文件。
——我们利用之前掌握的在变量的getter中进行延迟载入数据。
#import "ViewController.h" @interface ViewController ()
@property(nonatomic,strong) NSArray *arr1;
@end @implementation ViewController - (void)viewDidLoad {
self.arr1;
[super viewDidLoad];
} -(NSArray *)arr1{
if (_arr1==nil) {
NSString *path=[[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
_arr1=[NSArray arrayWithContentsOfFile:path];
NSLog(@"%@",_arr1);
}
return _arr1;
} @end
输出结果是:
{
icon = "icon_00";
name = "\U5929\U5929\U9177\U8dd1";
},
{
icon = "icon_01";
name = "\U5168\U6c11\U98de\U673a\U5927\U6218";
},
……
icon后面就是icon的名称,name后面也是name的名称,仅仅只是中文被转换成了Unicode形式,一个汉字就是一个\U****。
(3)九宫格计算
——关键在于利用 / 和 % 运算得到元素所在的行和列,注意%符号运算前后不能有CGFloat,都换成int类型较好。
——CGFloat事实上就是float和double的集合。全部用float和double的地方差点儿都能够用CGFloat。会依据当前系统自己主动解析,假设是32位系统,则用float,假设是64位系统,则解析成double。
- (void)viewDidLoad {
//定义总列数、每一个九宫格的宽高
int totalColumns=3;
CGFloat appW=90;
CGFloat appH=100;
//定义水平和垂直方面的间距
CGFloat marginX=(self.view.frame.size.width-totalColumns*appW)/(totalColumns+1);
CGFloat marginY=20; //依据arr1中数据数量来初始化并载入一个一个的UIVIew
for (int index=0; index<self.arr1.count; index++) {
//计算这个app在几行几列
int row=index/totalColumns;
int col=index%totalColumns;
//创建UIView
UIView *appView=[[UIView alloc]init];
//依据一些计算,确定不同UIView的位置
appView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);
appView.backgroundColor=[UIColor redColor];
[self.view addSubview:appView];
} [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
(4)往每一个appView里面加入一个UIImageView、UIlabel和UIButton。直接在for循环中加入,即创建UIView *appView的时候顺便把它里面的东西也创建了。
——当中,UIImageView里的图片用到取得图片的名称,这个能够存放在plist里面,我们把_arr1里相应的字典取出来使用就可以。
——重点是,UIButton的字体大小无法直接设置,而是用到UIbutton里的子视图titleLabel来设置。(由于UIButton里面事实上封装了两个子视图控件,一个是装文字的UILabel *titleLabel,一个装图片的UIImageView *imageView)
for (int index=0; index<self.arr1.count; index++) {
//计算这个app在几行几列
int row=index/totalColumns;
int col=index%totalColumns;
//创建UIView
UIView *appView=[[UIView alloc]init];
//依据一些计算,确定不同UIView的位置
appView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);
// appView.backgroundColor=[UIColor redColor];
[self.view addSubview:appView]; //依据索引拿到plist每一个字典的数据
NSDictionary *appDic=_arr1[index]; //往appView里添加子控件icon
//依据字典拿到里面的icon名称
UIImageView *appIcon=[[UIImageView alloc]init];
CGFloat iconW=65;
CGFloat iconH=65;
CGFloat iconX=(appW-iconW)/2;
CGFloat iconY=0;
appIcon.frame=CGRectMake(iconX, iconY, iconW, iconH);
appIcon.image=[UIImage imageNamed:appDic[@"icon"]];
[appView addSubview:appIcon]; //往appView里添加子控件label
UILabel *appLabel=[[UILabel alloc]init];
CGFloat labelW=appW;
CGFloat labelH=20;
CGFloat labelX=(appW-labelW)/2;
CGFloat labelY=iconY+iconH;
appLabel.frame=CGRectMake(labelX, labelY, labelW, labelH);
appLabel.text=appDic[@"name"];
appLabel.textAlignment=NSTextAlignmentCenter;
appLabel.font=[UIFont systemFontOfSize:14];
[appView addSubview:appLabel]; //往appView里添加子控件button
UIButton *appBtn=[[UIButton alloc]init];
CGFloat btnW=65;
CGFloat btnH=26;
CGFloat btnX=(appW-btnW)/2;
CGFloat btnY=labelY+labelH;
appBtn.frame=CGRectMake(btnX, btnY, btnW, btnH);
[appBtn setTitle:@"下载" forState:UIControlStateNormal];
appBtn.titleLabel.font=[UIFont systemFontOfSize:14];
[appBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];
[appBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateNormal];
[appView addSubview:appBtn];
}
(5)最重要的:字典转模型
使用字典的坏处:须要用key值调取和设置数据,有时候会出错,尽管能够用宏变量改进,可是更要命的写错了key值,没有错误提示。
模型:严格叫做模型数据。核心就是我们把字典当成一个对象,字典里面的几个数据,我们分别转换成对象的几个属性,我们调用和设置数据的时候直接是“对象.属性”就可以。
所以,我们须要创建一个类,这个专门用来存放数据,也就是常说的模型类。
本例中,创建一个JiuGongGe类,在.h中声明2个变量,和2种初始化方法(规范都是有2种初始化方法,事实上核心是一种,另外一种还是通过第一种来实现的)。
#import <Foundation/Foundation.h> @interface JiuGongGe : NSObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *icon; -(instancetype)initWithJiuGongGe:(NSDictionary *)dic;
+(instancetype)jiuGongGeWith:(NSDictionary *)dic; @end
在JiuGongGe.m中实现(注意写法,记忆):
#import "JiuGongGe.h" @implementation JiuGongGe -(instancetype)initWithJiuGongGe:(NSDictionary *)dic{
if (self=[super init]) {
self.name=dic[@"name"];
self.icon=dic[@"icon"];
}
return self;
} +(instancetype)jiuGongGeWith:(NSDictionary *)dic{
return [[JiuGongGe alloc]initWithJiuGongGe:dic];
} @end
事实上,我们的小标题是“字典转模型”,也就是说仅仅是把字典转换成模型(对象),原先字典存放在数组中的,然后通过数组[index]一个个调用字典,如今模型(对象)依旧存放在数组中。所以我们须要对数组的那个getter方法进行改进:(注意:须要在ViewController.m中#import "JiuGongGe.h",由于要实例化对象)
-(NSArray *)arr1{
if (_arr1==nil) {
NSString *path=[[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
NSArray *tmpArr=[NSArray arrayWithContentsOfFile:path];
NSMutableArray *muArr1=[[NSMutableArray alloc]init];
for (NSDictionary *dict in tmpArr) {
JiuGongGe *jiugognge=[JiuGongGe jiuGongGeWith:dict];
[muArr1 addObject:jiugognge];
}
_arr1=muArr1;
}
return _arr1;
}
在ViewDidLoad的那个for循环中,用到的地方都能够用对象.属性来调用数据了:
//依据索引拿到每一个对象,此处appDic名称未改,还是用之前取字典的那个变量,看的不太习惯
JiuGongGe *appDic=_arr1[index]; //往appView里添加子控件icon
……
appIcon.image=[UIImage imageNamed:appDic.icon]; //往appView里添加子控件label
appLabel.text=appDic.name;
(6)jiuGongGeWith:(NSDictionary *)dic;初始化方法的改进
——里面用到的类名,能够替换成self。由于防止这个类有子类,假设子类调用jiuGongGeWith:(NSDictionary *)dic;时调用到父类的这种方法,里面写得名字还是父类的名字,初始化结果是一个父类的对象,而不是子类的对象。所以用self,谁调用就初始化谁的对象。
(7)id类型和instancetype的说明
——instancetype和id一样,都是万能指针。
——iOS建议我们使用instancetype取代id。虽然官方非常多init方法的返回值也是id。
——使用id的优点就是,id是万能指针,我们不用操心它的返回值类型不匹配的问题。
——使用id的坏处:也正是由于它是万能指针,我们能够用随意指针接受这个返回值,比方NSString *str1=****,NSArray *arr1=****,这句代码写出来不会报错。可是有可能不是我们须要的返回值类型。
——使用instancetype的优点是,假设我们返回值是一个对象,那么你用上面两个随意指针接受这个返回值,它会有warning警告,我们用类对象JiuGongGe *jiugognge=***,就不会警告。
——instancetype仅仅能用在返回值类型上,不能像id一样用在參数上。
(8)利用xib图形化布局降低代码
xib和storyboard的差别在于,storyboard是描写叙述整个程序界面的,而xib多用于局部反复界面的描写叙述。
比方本例中有12个应用,每一个应用的视图都是一样的,能够用xib来实现,然后再把xib载入进来就可以。
xib的创建(用empty):
在ourXib中布局:
——给UIImageView和UILabel分别设置tag为10和20,方便调用。
——拖动控件到界面中,改变大小时候,UIImageView须要把size设置成Freeform才干调整大小。
ourXib设置好后,就能够调用:
——除了图片之外的资源,都须要用[NSBundle mainBundle]来调用。
——调用xib文件的方法是mainBundle的loadNibNamed方法。
for (int index=0; index<self.arr1.count; index++) {
//计算这个app在几行几列
int row=index/totalColumns;
int col=index%totalColumns; //依据索引拿到每一个对象
JiuGongGe *appDic=_arr1[index];
NSArray *xibArr=[[NSBundle mainBundle]loadNibNamed:@"ourXib" owner:nil options:nil];
UIView *xibView=[xibArr lastObject];
xibView.frame=CGRectMake(marginX+col*(marginX+appW), 30+row*(marginY+appH), appW, appH);
UIImageView *imgView2=(UIImageView *)[xibView viewWithTag:10];
imgView2.image=[UIImage imageNamed:appDic.icon]; UILabel *label2=(UILabel *)[xibView viewWithTag:20];
label2.text=appDic.name;
//加入到主view中
[self.view addSubview:xibView];
}
(9)xib文件和nib文件是什么关系?
——xib文件是我们开发人员在开发的时候看到的东西;
——而执行在用户手机里时,xib文件会被转化为nib文件。
我们能够在iOS Simulator产生的沙盒中查看。
——找不到资源库路径,直接用NSLog(@"%@",[NSBundle mainBundle);把路径打印出来。
查找发现,这个资源库中确实有个ourXib.nib文件,xib文件确实转化成nib文件了。
【iOS开发-48】九宫格布局案例:自己主动布局、字典转模型运用、id和instancetype差别、xib反复视图运用及与nib关系的更多相关文章
- iOS开发——高级技术精选OC篇&Runtime之字典转模型实战
Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...
- IOS不用AutoLayout也能实现自己主动布局的类(3)----MyRelativeLayout横空出世
对于IOS开发人员来说,在自己主动布局出现前仅仅能通过计算和设置frame的值来处理.这样设置位置时就会出现非常多硬编码,同一时候在屏幕旋转和不同屏幕之间适配时须要编码又一次调整位置和尺寸,我们也能够 ...
- iOS开发基础-九宫格坐标(6)
继续对iOS开发基础-九宫格坐标(5)中的代码进行优化. 优化思路:把字典转模型部分的数据处理操作也拿到模型类中去实现,即将 ViewController 类实现中 apps 方法搬到 WJQAppI ...
- iOS开发基础-九宫格坐标(5)
继续在iOS开发基础-九宫格坐标(4)的基础上进行优化. 一.改进思路 1)iOS开发基础-九宫格坐标(4)中 viewDidLoad 方法中的第21.22行对控件属性的设置能否拿到视图类 WJQAp ...
- iOS开发基础-九宫格坐标(4)
对iOS开发基础-九宫格坐标(3)的代码进行进一步优化. 新建一个 UIView 的子类,并命名为 WJQAppView ,将 appxib.xib 中的 UIView 对象与新建的视图类进行关联. ...
- iOS开发基础-九宫格坐标(3)之Xib
延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍 Xib 和 storyboard 的比较: 1) X ...
- iOS开发基础-九宫格坐标(2)之模型
在iOS开发基础-九宫格(1)中,属性变量 apps 是从plist文件中加载数据的,在 viewDidLoad 方法中的第20行.26行中,直接通过字典的键名来获取相应的信息,使得 ViewCont ...
- iOS 开发 ZFUI framework控件,使布局更简单
来自:http://www.jianshu.com/p/bcf86b170d9c 前言 为什么会写这个?因为在iOS开发中,界面的布局一直没有Android布局有那么多的方法和优势,我个人开发都是纯代 ...
- iOS开发基础-九宫格坐标(1)
一.功能分析 1)以九宫格展示图片信息,每一个 UIView 包含一个 UIImageView .一个 UILabel 和一个 UIButton . 2)加载App数据,根据数据长度创建对应的格子数: ...
随机推荐
- 求Sn=a+aa+aaa+…+aa…aaa(有n个a)…
时间限制: 1 Sec 内存限制: 128 MB 提交: 352 解决: 174 [提交][状态][讨论版] 题目描述 求Sn=a+aa+aaa+-+aa-aaa(有n个a)之值,其中a是一个数字 ...
- UVA 12206 - Stammering Aliens(后缀数组)
UVA 12206 - Stammering Aliens 题目链接 题意:给定一个序列,求出出现次数大于m,长度最长的子串的最大下标 思路:后缀数组.搞出height数组后,利用二分去查找就可以 这 ...
- Android做法说明(3)---Fragment使用app袋或v4包解析
Android做法说明(3)---Fragment使用app袋或v4包解析 1)问题简述 相信非常多的朋友在调用Fragment都会遇到以下的情况: watermark/2/text/aHR0cDov ...
- 如何使用 iOS 7 的 AVSpeechSynthesizer 国家有声读物(4)
控制:我们一定要学会控制 尤达大师(电影<星球大战>)有话:的关键在于控制.这本故事书是一个字一个字读出来,我愿意为它添加两个button,音调和语速,以便我们能够调整语音合成实时的时候. ...
- 第七章——DMVs和DMFs(3)——用DMV和DMF监控TempDB
原文:第七章--DMVs和DMFs(3)--用DMV和DMF监控TempDB 前言: 我们都知道TempDB是SQLServer的系统数据库,且SQLServer的日常运作严重依赖这个库.因此,监控T ...
- mfc 链接时错误 文件函数重复定义
我在HeaderFile里新建了一个函数,然后在程序里调用,一直出现这个错误,说这个函数重复定义, 发现是VS自动加到External dependencies里面了.把HeaderFile里的函数文 ...
- HDU 5012 Dice (BFS)
事实上是非常水的一道bfs,用字符串表示每一个状态,map判重就ok了. 题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5012 #include&l ...
- 新版本NDK环境结构(避Cygwin,超快)
曾经做Android的项目要用到NDK就必需要下载NDK,下载安装Cygwin(模拟Linux环境用的),下载CDT(Eclipse C/C++开发插件),还要配置编译器,环境变量... 麻烦到不想说 ...
- linux如果不进入window磁盘
最近,在windows8.1下安装ubuntu14.04,在windows沉睡.开放时间和进入选择进入系统选项,当时没有引起重视.他选择进入linux系统.但进入后,发现无法进入windows磁盘,百 ...
- SQL入门学习5-函数、为此、CASE表达式
6-1. 各种各样的函数 函数的种类 算数函数 字符串函数 日期函数 转换函数 聚合函数 1.1算术函数 数据类型:NUMERIC 是大多数DBMS都支持的一种数据类型. 通过NUMBERIC(全体位 ...