UI:这段时间的小总结
关于 UITAbleView 的重用机制 参考1 参考2 参考3
关于 UITableViewController 的知识来自博客 参考1 参考2 参考3
总结
一个工程的基本框架的规范写法
Appdelegate //这里存放一些工程的代理事件
Resource // 存放工程的公共资源 图片 音频
General // 存放共有的类,可以重复使用的共有的类
Macro // 存放一些宏定义
Vender //存放第三方类
Section {
模块一{ Controller Model View }
模块二{ Controller Model View }
模块三{ Controller Model View }
...
}
总结
(1)
UIScrollView (属性有:容量大小、内容区域偏移量、横竖的滚动条显示、是否可以滚动、方向锁、整页滚动、反弹效果、滚动条在滚动的时候缩放、)作用是:新闻页面的滚动
UIPageControl(属性有:页面总数、启动的当前页,总的页数,当前页的颜色,其余页的颜色)作用:与UIScrollView相结合使用
上面两个控件的对应的协议的方法的实现。
下面罗列 对于 UIScrollView 的一些方法的提示:
setContentOffset
backgroundColor
scorll.contentSize
indicatorStyle 滚动条的样式
showsHorizontalScrollIndicator
showsVerticalScrollIndicator
scorll.scrollEnabled
directionalLockEnabled
pagingEnabled
bounces
alwaysBounceHorizontal
alwaysBounceVertical
scrollsToTop
delegate
minimumZoomScale
maximumZoomScale
对应控件的触发事件
A发生滚动的时候触发 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
B将要进项拖拽的时候触发 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
C将要结束拖拽的时候触发 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset NS_AVAILABLE_IOS(5_0)
D 已经结束拖拽的时候触发 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
E 缩放的图像发生缩放的时候触发 - (void)scrollViewDidZoom:(UIScrollView *)scrollView NS_AVAILABLE_IOS(3_2)
F 将要减速 就是手指离开滚动条后 - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
G 已经结束减速 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
H 已经结束滚动 - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
I 设置 scrollView 的缩放视图 功能 《注意使用》 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
J 将要开始缩放的时候 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view NS_AVAILABLE_IOS(3_2)
K 已经结束缩放 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
L 对应上面点击状态条的时候 - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
M 已经偏移到最上端 时候触发 效果 是刷新一下当页面前的数据 (前提是 已经设置过 scrollToTop 属性为 YES 的时候) - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
下面罗列 对于 UIPageControl 的一些方法的提示:
currentPage
numberOfPages
pageIndicatorTintColor
currentPageIndicatorTintColor
添加一些点击事件(当页面的下标值改变的时候触发) [page addTarget:self action:@selector(handlePage:) forControlEvents:UIControlEventValueChanged];
这里一般都是要处理好某个 scroll 的偏移量,所以注意与上面的结合使用。
(2)
本周学习了,使用到 CXcode 创建本地数据 以后缀为 .plist 结尾的文件,注意会创建会获取本地文件的数据
实例:
NSString * filePath = [[NSBundle mainBundle]pathForResource:@"contacts" ofType:@"plist"];
self.dataDic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
首先得到 路径 然后再获取数据
UItableView 控件的总结
属性有:(页眉,页脚,右侧索引,每一区域的行数,行高,页眉页脚的对应颜色格式,字体的样式)
控件的样式有四种:其中注意区分默认模式与其他的模式的区别
继承与 UIViewController 类
使用到的时候,要让这个类服从对应的协议 <UITableViewDataSource,UITableViewDelegate>
使用到 UItableview 的时候 要设置数据源 dataSource的代理 的时候,一定要实现的两个方法是:
A设置区域的行数
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
B设置区域的个数
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{设置数据源,设置代理,设置为根视图 self.view = tableView;、添加导航栏系统自带按钮、读取数据,设置分割线的一些属性tableView.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);(分割线与上下左右的距离)以及分隔线的颜色}
使用一个tableView 的时候的步骤是:
A添加编辑按钮 就是在导航栏的右侧有一个可编辑的按钮
B重写 cell 的编辑事件 设置所有的 cell 是否可以被编辑,如果 editing Edit:YES 就是可以编辑 NO就是不可以被编辑的
实例代码:
-(void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
//editing Edit:YES 可编辑的 Done : NO 不可编辑
//设置 tableview 的编辑状态 目的就是让 tableView 处于编辑状态
[(UITableView *)self.view setEditing:editing animated:YES];
}
C指定某些区域可以编辑,某些区域不可以编辑
实例代码:
//设置哪些行可以被编辑
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 1) {//某行能否被修改
return YES;
}
return YES;
}
D设置 tableView 的编辑样式
实例代码
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 0) {//设置第一分组可以添加 一些数据
return UITableViewCellEditingStyleInsert;//插入样式
}
return UITableViewCellEditingStyleDelete;//删除样式
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0){
return @"点我删除";
}
E提交编辑的状态 提交编辑的状态的时刻被触发
实例代码
/提交编辑状态 提交编辑状态的时刻 被触发
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{要执行的数据更新:页面数据更新,数据库数据更新}
F设置cell 的移动
实例:
//移动(设置某些行的 cell 可以移动)(先打一个 BOOl 寻找方法)
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
//提交移动的操作 (先打 void 再寻找方法)
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{移动的操作,注意数据的同步}
//限定 cell 的移动界限 ----禁止跨区移动
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{}
我们可以使用一个UITableView的视图控制器类,来方便的进行编码 创建一个 UITableViewController 类
下面是 他的控制器类 与它(UITableView)的类的区别
UITableViewController 和 UIViewController 的区别
1.前者的根视图是 tableView 后者是 UIView
2.如果用 UIView 的话 需要再设置 dataSource ,前者不用再设置 dataSource 和 delegate ,同时也不用再服从协议,因为自身已经服从了, 而后者我们需要指定他的 dataSource 和 delegate
3.前者不用重写 setEdting:Animation : 方法控制 tabelview,后者需要指定
4.前者已经自动的帮我们生成了对应的 dataSource 的最基本最常用的协议的方法(需要使用,就注开就可以了),后者需要自己去手动添加相应的协议方法
注意在这个视图的控制器类的内部,已经为我们写好了,大多的一些常用的方法,我们使用的时候只要吧他注开就可以了。而且他的内部自己都为我们实现了一些
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault, // 左侧显示textLabel(不显示detailTextLabel),imageView可选(显示在最左边)
UITableViewCellStyleValue1, // 左侧显示textLabel、右侧显示detailTextLabel(默认蓝色),imageView可选(显示在最左边)
UITableViewCellStyleValue2, // 左侧依次显示textLabel(默认蓝色)和detailTextLabel,imageView可选(显示在最左边)
UITableViewCellStyleSubtitle // 左上方显示textLabel,左下方显示detailTextLabel(默认灰色),imageView可选(显示在最左边)
};
其他知识 :inRange:NSMakeRange(0, 3) 就是从下标为0的元素开始的3个元素, (NSUInteger i = [nn indexOfObject:@"元素1" inRange:NSMakeRange(0, 3)];)
这里有必要注意一些重用知识
为了在加载多条数据的时候吃内存的问题,减小系统的创建、释放对象的开销,但是不好的地方就是(他们每个 Cell 的内容都是一样的,如果要修改的话,都会跟着变化不能设置出有些不一样的行的区域 )我们主张自定义的 cell 我们可以在 cell上放一些自己定义的子视图
重用机制就是,找到可以重用的对象。吧对象赋予新的值,然后再再页面上刷出来,而已经显示的过得数据保存到一个重用池池中,内部用 tag 值去自己区别,其本质在于,创建一个可供重用的重用池,里面放上一些已经创建好的对象,需要的时候,从重用池中取出一个对象,进行赋值修改,使其成为我们需要的对象,然后再使用就可以了。这种方式在处理大量相似内容时,效率远高于创建释放的方式。
[objc]
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellid=@"cellid";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellid];//尝试从重用池中取一个出来使用
if (!cell) {//如果重用池中没有,就创建一个新的
cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid]autorelease];
}
return cell;
}
其实就是先尝试取重用池,重用池中没有空闲的就创建新的。
那么我们在日常的开发当中,这种重用的思想可以用到很多地方,比如一个界面有很多个UIButton,通过填充不同数据给不同情况下使用,那么我们其实就可以考虑使用重用,把这些东西都放入一个重用池(就是可变数组),然后用的时候再取出来使用,这样的开销要远远好于创建释放。当然,创建重用池的开销不能避免,但是通常情况,只需要几个可从用的对象,就可以完成若干的对象展示和使用问题。
那么什么地方可以使用这种重用机制呢?很简单,如果你有一大批相似的东西要处理(可封装为同一对象),但是每次只是处理其中的一小部分(或界面展示一小部分),那么就可以使用重用机制了。
要熟练的使用重用的方法。
(3)对于UIImage 类的分类 (用于我们在为 cell 设置统一规格的图片的时候要使用到的)
_photoView.layer.masksToBounds = YES;//当绘制底层的边界的时候,本控件也和边界一起绘制(注意这里的 _photoView是一个视图它里面有一个相框)
在.h 里
//获取指定大小的图片
-(UIImage *)scaleToSize:(CGSize)size;
在 .m 里
-(UIImage *)scaleToSize:(CGSize)size{
//绘制图片
//创建一个 bitmap 的上下文,并指定为当前使用的 context
UIGraphicsBeginImageContext(size);
//根据外界传入的大小绘制改变大小后的图片
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
//从当前的 context 获取改变大小后的图片
UIImage * scaleImage = UIGraphicsGetImageFromCurrentImageContext();
//使我们当前的 context 从栈顶出栈
UIGraphicsEndImageContext();
//返回改变大小后的图片
return scaleImage;
}
(4)
UINavigationController 控件
总结:UINavigationController 控制器(继承与 UIViewController ),就是IOS 提供的多视图控制器,可以用来管理多个视图控制器
这个导航控制器自身也有一个根视图 在最上端还有一个导航条 ( UINavigationBar )使用来管理我们所有的视图控制器,试图控制器是用来管理视图的,
RootViewController * RootVC = [[RootViewController alloc]init];
//创建一个导航控制器 (并且制定 RootVC 为导航控制器的根视图控制器)
UINavigationController * navl = [[UINavigationController alloc]initWithRootViewController:RootVC];
//指定导航控制器为窗口根视图控制器 (window -> navl -> RootVC)
self.window.rootViewController = navl;
[RootVC release];
UINavigationContaller 的属性(总结):
导航栏的颜色 self.navigationController.navigationBar.barTintColor
毛玻璃效果 self.navigationController.navigationBar.translucent (默认是打开的,如果关闭视图将从(0,64)开始布局)如果不关闭的话,从(0,0)开始布局
导航条是否隐藏 navigationBarHidden navigationBar.hidden
导航条的标题内容的颜色 navigationBar.tintColor
{//如果为导航条控件添加按钮(按钮上的图片会被渲染)我们要对图片进行渲染 例如Button上添加的图片后,吧图片的渲染改为原图模式 [[UIImage imageNamed:@"NavBtnBack"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
//当导航条上的控件为图片的时候,我们需要对图片进行一个渲染设置,默认的系统的渲染是渲染模板,如果需要设置为原图,则需要设置为原图渲染
}
设置当前界面的导航栏的属性<当前界面的哦>
//5.设置导航条的标题字体大小和颜色
NSDictionary * dic = @{NSFontAttributeName:[UIFont systemFontOfSize:20],NSForegroundColorAttributeName:[UIColor orangeColor]};
self.navigationController.navigationBar.titleTextAttributes = dic;
//6.设置背景图片
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"NavBar_64"] forBarMetrics:UIBarMetricsDefault];
不同尺寸的图片,导航条的显示效果不一样
小于 44 像素 将图片拉伸,同时铺满状态条和导航条的空间
等于 44 像素 只会显示在导航条
大于 44 像素小于 64像素 将图片平铺在状态条和导航条的空间
等于 64 像素 图片正好显示在导航条以及状态条上
为导航控制器设置 左右 Button
//设置左边内容
UIBarButtonItem * left = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(handleLeftAction:)];
self.navigationItem.leftBarButtonItem = left;
[left release];
/设置右边内容
// UIBarButtonItem * right = [[UIBarButtonItem alloc]initWithTitle:@"右边内容" style:UIBarButtonItemStylePlain target:self action:@selector(handleRightAction:)];
UIBarButtonItem * right = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"NavBtnBack"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:segment action:@selector(handleRightAction:)];
自定义一个Button 在这个 Button上添加点击事件 进入到下一页实现如下
-(void)pushToNext:(UIButton * )sender{//进入下一个页面是用 pushToNext
//创建第二个视图控制器
SecondViewController * SecondVC = [[SecondViewController alloc]init];
//利用当前控制器的导航控制器 去进入到下一个页面(最好改变一下要跳闸到的页面的背景颜色,不染有卡顿效果)
[self.navigationController pushViewController:SecondVC animated:YES];
//释放所有权
[SecondVC release];
返回上一个页面的实现实例:
-(void)pushToNext2:(UIButton *)button2{
//屏幕上显示的是栈顶元素
//导航控制器以 栈 的形式管理单视图控制器 push 入栈,这个试图控制器就受导航控制器管理 pop 是出栈(出栈对应的 viewColler 视图控制器的空间就被回收了)
//UINavigationController 的 viewControllers 属性 就是当前控制器所管理的 所有的单视图控制器
for (UINavigationController * vc in self.navigationController.viewControllers) {
NSLog(@"返回第二个页面 当前视图控制器为%@", vc);
if ([vc isKindOfClass:[SecondViewController class]]) {
[self.navigationController popToViewController:vc animated:YES];
}} }
//设置导航条的标题
self.navigationItem.title = @"行健主页面<第一页面>";
//设置导航条的标题视图
// self.navigationItem.titleView =
//设置返回按钮的标题
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
在页面之间传值的时候要注意,页面的不同时机,我们可以处理不同的事件(这里可以查看 UIView 类里面的一些协议的方法,结合在复习)
//屏幕上显示的是栈顶元素
//导航控制器以 栈 的形式管理单视图控制器 push 入栈,这个试图控制器就受导航控制器管理 pop 是出栈(出栈对应的 viewColler 视图控制器的空间就被回收了)
//UINavigationController 的 viewControllers 属性 就是当前控制器所管理的 所有的单视图控制器
}
(5)
懒加载,就是何时需要,何时调用方法
例子:
@implementation RootViewController
//懒加载 (其实就是 getter 方法)何时需要 何时创建
-(UILabel *)resultLable{
if (!_resultLabel) {
//创建一个 label
}
return _resultLabel;
}
(页面之间的传值,有三类)
界面之间的传值
1.从前往后传值——利用属性传值
2.从后往前传值——代理传值
——Block传值(自己查阅学习,没有实现)
3.间隔几个页面的的传值(多页面之间的传值)——单例传值
假设页面2要把数值传入到页面1
代理传值的步骤:
(页面2)设置协议、(页面2)定义属性、(页面1)(页面1在跳闸页面2之前)指定代理对象、(页面1)当前的对象在的类要服从协议、(页面1)代理对象要实现协议的方法、(页面2)(在页面2消失的时候)吧对应的数据作为协议的参数传入第一个页面
单例传值步骤:
A首先要有一个单例
B在单例类里添加一个类方法 (便利构造器)并且保证得到的始终是同一个对象 所以说是静态变量
C在单例类中为单例对象添加属性,存储传输的数据
D把传输的数据保存到到单例的属性中
E当需要数据时,就从单例的属性中得到传递的数据
单例:就是只有一个对象,在程序退出时候被回收。
单例的命名规则,我们要模仿系统的
[NSFileManager defaultManager];
[[UIScreen mainScreen]bounds];
[UIApplication sharedApplication];
[NSUserDefaults standardUserDefaults];
[NSBundle mainBundle];
在单例类的.m文件里我们通常这样设置 用来保存数据的单例对象:
定义全局静态变量
static 单例类 * 单例对象 = nil;
//(为了保证单例类只有一个对象,我们用静态变量来存储对象的指针,一旦发现指针变量为空,则创建单例对象,否则直接返回原来对象的地址)实现
//对象只有 alloc 没有 release ,这样就存在内存泄露的问题,一般创建单例是用来解决特定的问题,不到万不得已,一般是不会使用单例
+(单例类 *)sharedSingleton{
//加锁 安全处理
@synchronized(self){
if (!单例对象) {
单例对象 = [[单例类 alloc]init];
}}
return 单例对象;
}