iOS|iOS 小而精的Demo(1) 通讯录


iOS|iOS 小而精的Demo(1) 通讯录
文章图片
contact-demo3.gif
这就是我参考 别人的文章写的第一个demo。通过这个简单的demo,我学会了:

1: 巩固了OC的语法,比如上篇文章写的copy属性修饰符、#pragma mark的使用、私有成员等。
2:使用简单的UIKit方法,主要是UITableview。
3:MVC设计模式的实际应用。
4: iOS程序的启动顺序。
接下来就结合Demo分别总结一下上述几个方面,其中OC的语法就跳过。
UITableView的使用方法
  • 创建
[[UITableView alloc] initWithFrame:(CGRect)frame style:(UITableViewStyle)style];

其中frame 就是tableview的边框, UITableViewStyle是风格,是一个常量:
typedef enum { UITableViewStylePlain, //纯列表模式 UITableViewStyleGrouped //分组模式 } UITableViewStyle;

  • 使用
    根据MVC设计原则,View使用之前要先指定数据源(DataSource)和委托(Delegate)。一般就是委托为ViewController。
_tableView.dataSource = self; _tableView.delegate = self;

因此,就要在ViewController里实现UITableViewDataSource和
UITableViewDelegate协议。
其中, 数据源协议的方法主要是
-(NSInteger)numberOfSectionsInTableView: //返回分组数 -(NSInteger)tableView:numberOfRowsInSection: //返回每组的行数 -(UITableViewCell*)tableView:cellForRowAtIndexPath://返回每行的单元格 -(NSString*)tableView:titleForHeaderInSection://返回每组头标题名称 -(NSString*)tableView:titleForFooterInSection://返回每组尾标题名称 -(NSArray*)sectionIndexTitlesForTableView://返回每组标索引

这些方法都是View委托实现的,操作的实体就是数据源,由此达到了View与Model通过Controller通信。
代理协议的方法主要是:
-(CGFloat)tableView:heightForHeaderInSection://设置分组标题内容高度 -(CGFloat)tableView:heightForFooterInSection://设置尾部说明内容高度 -(CGFloat)tableView:heightForRowAtIndexPath://设置每行高度 -(void)tableView:didSelectRowAtIndexPath://点击某一行行为

使用UITableViewCell的一个细节需要注意,也是性能的一个优化。
UITableView中的单元格cell是在显示到用户可视区域后创建的,那么如果用户往下滚动就会继续创建显示在屏幕上的单元格,如果用户向上滚动返回到查看过的内容时同样会重新创建之前已经创建过的单元格。如此一来就重复创建了很多cell,导致内存浪费。
在UITableView内部有一个缓存池,初始化时使用initWithStyle:(UITableViewCellStyle) reuseIdentifier:(NSString *)方法指定一个可重用标识,就可以将这个cell放到缓存池。然后在使用时使用指定的标识去缓存池中取得对应的cell然后修改cell内容即可,不同类型的cell可以指定不同的标示符。
//由于此方法调用十分频繁,cell的标示声明成静态变量有利于性能优化 static NSString *cellIdentifier=@"UITableViewCellIdentifierKey1"; //首先根据标识去缓存池取 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //如果缓存池没有到则重新创建并放到缓存池中 if(!cell) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; }

  1. -(UITableViewCell *)tableView:cellForRowAtIndexPath:方法调用很频繁,无论是初始化、上下滚动、刷新都会调用此方法,所有在这里执行的操作一定要注意性能;
  1. 可重用标识可以有多个,如果在UITableView中有多类结构不同的Cell,可以通过这个标识进行缓存和重新;
MVC设计模式的实际使用

iOS|iOS 小而精的Demo(1) 通讯录
文章图片
MVC经典图解
如图所示:
  1. Model和View永远不能相互通信,只能通过Controller传递。
  1. Controller可以直接与Model对话(读写调用Model),Model通过
    Notification和KVO机制与Controller间接通信。
  2. Controller可以直接与View对话(通过outlet,直接操作View,outlet直接对应到View中的控件),View通过 action向Controller报告事件的发生(如用户Touch我了)。Controller是View的直接数据源(数据很可能是 Controller从Model中取得的)。Controller是View的代理(delegate),以同步View与Controller。
关于MVC的理论就不说了,google一大堆。在本Demo中,Model就是联系人信息Contact和分组信息ContactGroup,它们定义了数据的格式,一般还可以定义读写的接口;View就是UIWindow、UITableView和UIToolBar,主要说UITableView,它定义了在界面上绘制那些视图元素,怎么绘制,在哪绘制,并不知道这些视图上显示什么数据;Controller主要就是MyViewController,这个是自定义的,它维护了视图tableView,也维护了数据contacts,当然它要实现对应的数据源和委托协议。
iOS启动过程

iOS|iOS 小而精的Demo(1) 通讯录
文章图片
iOS启动过程1
iOS|iOS 小而精的Demo(1) 通讯录
文章图片
iOS启动过程2
在本Demo中,具体的执行顺序是:
1.main.m中的UIApplicationMain, 设置整个app的委托为AppDelegate,开始监听事件循环。
2.AppDelegate.m中的didFinishLaunchingWithOptions:方法,在这里面创建UIWindow并设置它的rootViewController为MyViewController,那UIWindow的事件就委托给MyViewController了。
3.MyViewController.m中的viewDidLoad方法,在这里开始初始化数据以及添加子视图。
这样,视图就可以显示了,在视图的操作都会传递到MyViewController中的对应方法中去,这些方法可能更新Model中的数据,然后刷新视图,展示更新。
【iOS|iOS 小而精的Demo(1) 通讯录】接下来可以在此基础上增加导航栏,也学会数据存取的几种方法。

    推荐阅读