【iOS发展-44】通过案例谈iOS重构:合并、格式化输出、宏观变量、使用数组来存储数据字典,而且使用plist最终的知识
我们今天的情况下是第一个例子,下面的5一来通过切换页上一页下一页:
(1)第一步,基本是以非常傻非常直接的方式来创建。这里用到的主要点有:
——把对象变量设置为全局变量使得能够在其它方法中调用来设置它们的属性
——设置了一个全局变量index,默认是0。然后通过添加降低这个index值并结合switch来调用不同的数据。
——利用先调用一次change方法初始化页面。使得页面定格在第一帧。
——利用button的enabled属性来设置button能否够被点击,然后结合index的值分别在第1张和第5张时分别把上一张和下一张button设置为灰色不可点击。当然初始化页面的时候也要推断一下把上一张button设置为灰色。
——这里的change方法和btnCheck方法都是代码重构的产物,由于这两个方法都须要在preOne和nextOne方法中被调用,所以为了避免反复代码,所以把这些反复的部分都封装成了方法。
#import "ViewController.h"
//把一些对象定义成全局变量。这样能够多个方法中调用
@interface ViewController (){
UIButton *btnPre;
UIButton *btnNext;
UILabel *numLabel;
UILabel *descLabel;
UIImageView *imgView1;
int index1;
} @end @implementation ViewController - (void)viewDidLoad { btnPre=[UIButton buttonWithType:UIButtonTypeRoundedRect];
btnPre.frame=CGRectMake(50, 150, 60, 30);
[btnPre setTitle:@"上一张" forState:UIControlStateNormal];
[btnPre addTarget:self action:@selector(preOne) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnPre];
btnNext=[UIButton buttonWithType:UIButtonTypeRoundedRect];
btnNext.frame=CGRectMake(250, 150, 60, 30);
[btnNext setTitle:@"下一张" forState:UIControlStateNormal];
[btnNext addTarget:self action:@selector(nextOne) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnNext]; numLabel=[[UILabel alloc]init];
numLabel.frame=CGRectMake(170, 50, 100, 30);
[self.view addSubview:numLabel]; descLabel=[[UILabel alloc]init];
descLabel.frame=CGRectMake(110, 300, 200, 30);
[self.view addSubview:descLabel]; imgView1=[[UIImageView alloc]init];
imgView1.frame=CGRectMake(130, 100, 100, 100);
[self.view addSubview:imgView1]; //由于一開始的index为0。所以我们直接调用change方法,相当于把第一帧的页面调出来初始化页面
[self change]; btnPre.enabled=(index1!=0); [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} -(void)preOne{
index1--;
[self btnCheck];
[self change];
} -(void)nextOne{
index1++;
[self btnCheck];
[self change];
} //按钮的enabled属性,假设是NO,则变成灰色。 事实上下面语句是三目运算推到而来
-(void)btnCheck{
btnPre.enabled=(index1!=0);
btnNext.enabled=(index1!=4);
} -(void)change{
switch (index1) {
case 0:
numLabel.text=@"1/5";
descLabel.text=@"This is the letter A";
imgView1.image=[UIImage imageNamed:@"a.png"];
break;
case 1:
numLabel.text=@"2/5";
descLabel.text=@"This is the letter B";
imgView1.image=[UIImage imageNamed:@"b.png"];
break;
case 2:
numLabel.text=@"3/5";
descLabel.text=@"This is the letter C";
imgView1.image=[UIImage imageNamed:@"c.png"];
break;
case 3:
numLabel.text=@"4/5";
descLabel.text=@"This is the letter D";
imgView1.image=[UIImage imageNamed:@"d.png"];
break;
case 4:
numLabel.text=@"5/5";
descLabel.text=@"This is the letter E";
imgView1.image=[UIImage imageNamed:@"e.png"];
break;
default:
break;
}
} @end
(2)对switch部分进行改造:利用格式化输出重构代码:用第二行代码取代凝视掉的那5行代码。
-(void)change{
numLabel.text=[NSString stringWithFormat:@"%d/%d",index1+1,5];
switch (index1) {
case 0:
//numLabel.text=@"1/5";
descLabel.text=@"This is the letter A";
imgView1.image=[UIImage imageNamed:@"a.png"];
break;
case 1:
//numLabel.text=@"2/5";
descLabel.text=@"This is the letter B";
imgView1.image=[UIImage imageNamed:@"b.png"];
break;
case 2:
//numLabel.text=@"3/5";
descLabel.text=@"This is the letter C";
imgView1.image=[UIImage imageNamed:@"c.png"];
break;
case 3:
//numLabel.text=@"4/5";
descLabel.text=@"This is the letter D";
imgView1.image=[UIImage imageNamed:@"d.png"];
break;
case 4:
//numLabel.text=@"5/5";
descLabel.text=@"This is the letter E";
imgView1.image=[UIImage imageNamed:@"e.png"];
break;
default:
break;
}
}
(3)利用字典和数组把数据单独出来,并实现数据的删减和代码之间的独立,即增减数据后,不须要改动我们显示“总页数”等这些代码,但增减数据仍须要通过增减代码来实现。(在开头定义一个全局变量NSArray *arr1)
- (void)viewDidLoad {
……
NSMutableDictionary *dic1=[NSMutableDictionary dictionary];
dic1[@"icon"]=@"a.png";
dic1[@"desc"]=@"This is the letter A"; NSMutableDictionary *dic2=[NSMutableDictionary dictionary];
dic2[@"icon"]=@"b.png";
dic2[@"desc"]=@"This is the letter B"; NSMutableDictionary *dic3=[NSMutableDictionary dictionary];
dic3[@"icon"]=@"c.png";
dic3[@"desc"]=@"This is the letter C"; NSMutableDictionary *dic4=[NSMutableDictionary dictionary];
dic4[@"icon"]=@"d.png";
dic4[@"desc"]=@"This is the letter D"; NSMutableDictionary *dic5=[NSMutableDictionary dictionary];
dic5[@"icon"]=@"e.png";
dic5[@"desc"]=@"This is the letter E"; arr1=[NSArray arrayWithObjects:dic1,dic2,dic3,dic4,dic5, nil];
//以上代码须要加入在self change上。否则这个初始化是没有数据能够初始化的
[self change]; btnPre.enabled=(index1!=0); [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
初始化了数据之后。其它地方都能够进行简化了。比方计算页数,比方取数据,就能够利用字典和数组来取数据:
-(void)btnCheck{
btnPre.enabled=(index1!=0);
btnNext.enabled=(index1!=arr1.count-1);//计算页数的相关代码
}
-(void)change{
numLabel.text=[NSString stringWithFormat:@"%d/%d",index1+1,5];
//取出相应的数据
NSDictionary *dic=arr1[index1];
//设置icon图片
imgView1.image=[UIImage imageNamed:dic[@"icon"]];
//设置描写叙述文字
descLabel.text=dic[@"desc"];
}
以上一步的优点在于我们增减数据的时候仅仅须要在增减新的dic6等等。然后把dic6之类的加入到数组arr1中就可以。
其余地方不须要手动改动数字,由于我们引用数字的地方是用了数组的count属性。引用数据的地方使用了数组和字典的相关属性,不是写死的,而是活的。
(4)利用宏变量避免代码出现错误的可能性,尤其是在多人协作开发时。利用宏变量的提示可降低误输入的可能。
#define kICONKEY @"icon"
#define kDESCRIP @"desc"
所以其它响应的地方都应该替换成宏变量。
(5)利用property创建变量,注意。尽管老师说建议控件对象用weak。而一般对象用strong,可是发现。使用weak根本无法实例化对象,所以此处临时还是用strong。等查明原因再说。
响应的以下的变量都能够用_****取代或者用self.***取代。
建议此处用后者。
@interface ViewController (){
// UIButton *btnPre;
// UIButton *btnNext;
// UILabel *numLabel;
// UILabel *descLabel;
// UIImageView *imgView1;
// int index1;
}
@property(nonatomic,retain) UIButton *btnPre;
@property(nonatomic,retain) UIButton *btnNext;
@property(nonatomic,retain) UILabel *numLabel;
@property(nonatomic,retain) UILabel *descLabel;
@property(nonatomic,strong) UIImageView *imgView1;
@property(nonatomic,strong) NSArray *arr1;
@property(nonatomic,assign) int index1; @end
(6)延迟载入,懒载入。仅仅有须要的时候才初始化载入数据。
也就是说,我们能够把数据型的属性的初始化放在这个数据的getter方法中。且做一个推断是否要又一次载入。
我们默认的arr1的getter方法是:
-(NSArray *)arr1{
return _arr1;
}
改动为例如以下。即假设这个数组载入过数据,则不用反复载入,并且是用self.arr1调用到它的时候才载入,这就是延迟载入:
-(NSArray *)arr1{
if (_arr1==nil) {//此处用_arr1而不用self.arr1是避免死循环。由于self.arr1也是调用这个函数。会一直循环调用自身
NSMutableDictionary *dic1=[NSMutableDictionary dictionary];
dic1[kICONKEY]=@"a.png";
dic1[kDESCRIP]=@"This is the letter A"; NSMutableDictionary *dic2=[NSMutableDictionary dictionary];
dic2[kICONKEY]=@"b.png";
dic2[kDESCRIP]=@"This is the letter B"; NSMutableDictionary *dic3=[NSMutableDictionary dictionary];
dic3[kICONKEY]=@"c.png";
dic3[kDESCRIP]=@"This is the letter C"; NSMutableDictionary *dic4=[NSMutableDictionary dictionary];
dic4[kICONKEY]=@"d.png";
dic4[kDESCRIP]=@"This is the letter D"; NSMutableDictionary *dic5=[NSMutableDictionary dictionary];
dic5[kICONKEY]=@"e.png";
dic5[kDESCRIP]=@"This is the letter E"; _arr1=[NSArray arrayWithObjects:dic1,dic2,dic3,dic4,dic5, nil];
} return _arr1;
}
(7)再进一步:把数据独立存放在plist中,以后增减数据仅仅是改动plist文件,而不须要在代码中增减数据。
先创建plist文件:
然后,在代码中引用。凝视掉的那些数据都已经存放在plist文件里了。用最以下的几行来使用plist文件就可以,以后有增减数据,仅仅要修改plist文件,不须要修改代码:
-(NSArray *)arr1{
if (_arr1==nil) {
// NSMutableDictionary *dic1=[NSMutableDictionary dictionary];
// dic1[kICONKEY]=@"a.png";
// dic1[kDESCRIP]=@"This is the letter A";
//
// NSMutableDictionary *dic2=[NSMutableDictionary dictionary];
// dic2[kICONKEY]=@"b.png";
// dic2[kDESCRIP]=@"This is the letter B";
//
// NSMutableDictionary *dic3=[NSMutableDictionary dictionary];
// dic3[kICONKEY]=@"c.png";
// dic3[kDESCRIP]=@"This is the letter C";
//
// NSMutableDictionary *dic4=[NSMutableDictionary dictionary];
// dic4[kICONKEY]=@"d.png";
// dic4[kDESCRIP]=@"This is the letter D";
//
// NSMutableDictionary *dic5=[NSMutableDictionary dictionary];
// dic5[kICONKEY]=@"e.png";
// dic5[kDESCRIP]=@"This is the letter E"; // _arr1=[NSArray arrayWithObjects:dic1,dic2,dic3,dic4,dic5, nil]; //取得mainBundle。即程序主目录
NSBundle *path=[NSBundle mainBundle];
//用取得的mainBundle来查找文件,返回路径
NSString *pathFile=[path pathForResource:@"imgdata" ofType:@"plist"];
_arr1=[NSArray arrayWithContentsOfFile:pathFile];
} return _arr1;
}
(8)补充:怎么查看这个mainBundle资源库?
NSBundle* path=[NSBundle mainBundle]就是拿到这个资源库的路径。返回的是NSBundle对象,事实上是一个路径,能够通过这个来訪问资源库里面的全部资源。事实上它详细放在哪里?无须上网查找,直接用NSLog(@"%@",path);把这个路径打印出来不就ok了嘛。
NSBundle </Users/Andy/Library/Developer/CoreSimulator/Devices/64EDA842-5B0C-448D-BF2B-B063D09B60CB/data/Containers/Bundle/Application/E0E6FE95-99D1-4F70-84CD-D73059EA71DF/hello.app>
顺着上面这个路径就找到了这个hello.app包>>>右击显示包内容。
大功告成。
(9)图片的大小不一样,怎样是好?
一般我们会给UIImageView设定好固定的宽高,可是图片假设有大有小怎么办?须要用到调用“内容模式”contentMode这个属性。即调整UIImageView里面内容怎么缩放摆放的。
一般默认的是拉伸图片直至填满整个UIViewView。这样一般会改变图片的宽高比,使得图片变形。我们一般经常使用的时,在保持图片宽高比的情况下,尽可能的填充这个UIImageView就可以,这个属性以及值就是(以上代码为什么没有加入,由于我们做得时候就设定了图片都是100*100,UIImageView也是100*100,所以不须要用到这个属性):
self.imgView1.contentMode=UIViewContentModeScaleAspectFit;
(10)文字太多。自己主动换行怎么设置?
以描写叙述文字的descLabel为例。我们本案例中文字并非非常多,且给了这个descLabel宽度200,足够用。全部仅仅有一行。假设我们把宽度设置为100,就发现显示不下。最后有个...表示省略内容。设置多行,有个numberOfLine属性。你能够设置详细的2,3,4等行数数字。也能够直接用0,表示无所谓多少行。
须要注意的时,设置多行的时候,你的descLabel高度要足够,不然依旧是显示...省略号。我们原先是30的高度,此处改成了60。
self.descLabel.frame=CGRectMake(110, 300, 100, 60);
self.descLabel.numberOfLines=0;
总结:要自己动手。尽管都明确当中原理,可是真正操作起来,会遇到一些非常小可是非常重要的问题,一个一个的解决定,这种积累,预计新手和差异老兵。
版权声明:本文博客原创文章。博客,未经同意,不得转载。
【iOS发展-44】通过案例谈iOS重构:合并、格式化输出、宏观变量、使用数组来存储数据字典,而且使用plist最终的知识的更多相关文章
- 浅谈iOS视频开发
浅谈iOS视频开发 这段时间对视频开发进行了一些了解,在这里和大家分享一下我自己觉得学习步骤和资料,希望对那些对视频感兴趣的朋友有些帮助. 一.iOS系统自带播放器 要了解iOS视频开发,首先我们从 ...
- 浅谈iOS中的userAgent
浅谈iOS中的userAgent User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...
- 从实践谈iOS生命周期
从实践谈iOS生命周期 个人感觉生命周期无论在Android,还是iOS都是很重要的概念,因为在每个声明周期的状态下我们可以做很多预加载或者处理的操作.因此在这里主要总结下ViewController ...
- iOS发展 - 使用您自己的自定义字体
一位同事问我最后一次,XXapp字体如何萌啊? 我也想提出萌哒哒的字体!然后,今天有这blog. 首先,我们正处于iOS发展,苹果给了我们很多的字体,当然,我就不一一列举在这里,英文,小汤表示看不懂啦 ...
- 谈一谈iOS事件的产生和传递
谈一谈iOS事件的产生和传递 1.事件的产生 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中. UIApplication会从事件队列中取出最前面的事件,并将事件 ...
- 【iOS开发-56】案例BUG:button的enabled、控件的userInteractionEnabled以及两种提示框UIAlert和UIActionSheet
接上述案例找BUG:[iOS开发-51]案例学习:动画新写法.删除子视图.视图顺序.延迟方法.button多功能使用方法及icon图标和启动页设置 (1)BUG:答案满了就不能再点击optionbut ...
- 浅谈iOS多线程
浅谈iOS多线程 首先,先看看进程和线程的概念. 图1.1 这一块不难理解,重点点下他们的几个重要区别: 1,地址空间和资源:进程可以申请和拥有系统资源,线程不行.资源进程间相互独立,同一进程的各线程 ...
- 浅谈iOS开发中多语言的字符串排序
一.前言 在iOS开发中,一个经常的场景是利用tableview展示一组数据,以很多首歌曲为例子.为了便于查找,一般会把这些歌曲按照一定的顺序排列,还会加上索引条以便于快速定位. 由于歌曲名可能有数字 ...
- iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变
iOS 9的新的改变 iOS SDK Release Notes for iOS 9 说了些改变 看了下还算能理解!!!有兴趣可以看看哈!!!不喜勿喷!!后面的对于废除的方法什么有用感觉!!! ...
随机推荐
- jackson 转json. 过滤null值
@Test public void tttttt() throws JsonGenerationException, JsonMappingException, IOException { Objec ...
- (诊断)为GitHub添加SSH key时出现“Could not open a connection to your authentication agent”错误的应对方案(转)
在为windows 环境下的github账户添加SSH key时,需要在Git Bash执行如下命令: 第一步:检查已有的SSH keys $ ls -al ~/.ssh 第二步:生成新的SSH ke ...
- C++中用rand()和srand()产生随机数方法介绍
标准库<cstdlib>(被包含于<iostream>中)提供两个帮助生成伪随机数的函数: 函数一:int rand(void): 从srand (seed)中指定的see ...
- 在不同编译环境中如何使用sleep()函数
今天在学习有关时间函数时,想让程序暂时挂起,一段时间后在继续执行! 用到了系统函数sleep(): 在vc下sleep函数是以毫秒为单位,如果想让其停留3秒,需要这样做 sleep(3*1000); ...
- poj3819 Coverage (求直线与圆的交占直线的百分比 )
题意:给你一条直线和若干个圆,求圆与直线相交的长度占整条直线的比例 解题思路:通过定比分点的方法求出圆与直线的交占圆的比例. 第一步:(确定投影的方向是x轴还是y轴) (1)当直线的line.s(x, ...
- 算法练习之DP 求LCM (最长公共子序列)
1. 对于序列x[1,i]和y[1,j],推导递推公式1.a 假设当前元素同样,那么就将当前最大同样数+12.b 假设当前元素不同.那么就把当前最大同样数"传递"下去 因此递推公式 ...
- Java 生成本文文件的时候,Dos格式转成Unix格式
仅仅须要在生成文本的最后 加上 sb.append("\n\r");就可以 是/n/r 不是/r/n
- C语言,const
const意味着“只读” ubunto下的实验 1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的.如果你曾花很多时间清理 ...
- C++内存管理(超长)
[导语] 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对C++的痛恨,但内存管理在C++中无处不 ...
- Eclipse相关集锦第二季
Eclipse相关的问题第二季开始了,这些问题都是我平时遇到的,然后记录下来备忘,帮助到别人最好不过了. 1.Unable to execute dex: GC overhead limit exce ...