学了两天UITableView,从一开始无从入手到现在慢慢的了解各种各样的内容
不过还仅仅停留在“有点印象”的水平上,还有很多很多东西需要学。在这里记下学的过程中遇到的种种问题还有思考后得到的答案
很多都是与UITableView无关的基础的知识就是了。。。
一、#import与@class的区别
#import会包含类里面的变量和方法,而@class则只告诉编译器后面声明的名称是类的名称,所以一般在头文件中可以使用@class(因为不用知道实体变量和方法),而实现部分因为要用到里面的方法等,所以需要用#import来包含进来。
那么使用@class的时机?如果#import的地方多了,当一开始那个头文件有变化的话,将会导致后面所有#import的类都要重新编译一次,但是@class则不会。所以在类多的场合可以考虑使用@class(不过现在文件还少所以直接#import吧)
另一种情况下,如果有相互依赖关系的,比如两边都需要用到的,使用#import互相包含的话会报错,但使用@class在头文件中互相声明则不会。
总结起来的话,@class是放在interface的,只是为了引用这个类来使用,而在implementation里还是需要用#import把声明的类加进来
二、委托、协议
在知乎里看到了一篇比较详细而且容易懂的
http://www.zhihu.com/question/19827157
看了一遍自己的总结:
一个很多人用的例子,老板委托秘书做事,这就是委托。一开始我觉得这例子也太抽象了吧。。那其实老板自己去做的话不也可以吗。。
直到看到了某一层 结合最近一直弄这几个之间的关系,忽然有点懂了。。
软件里有个UITableView,这个【负责显示了表格】,但是当你点他,他又【不能没反应】,但是他又【只想好好地显示好界面】就行,这个时候为了反应你他就把反应这件事【委托】给了UITableViewController来做,使用某个方法,来完成反应
其实就是一种设计思想,贯彻了MVC的设计模式。好处是可以直接把那个表格放到别的地方使用,有效地利用
那么要怎么知道委托给谁?怎么判断哪个可以委托?这时候协议就出现了。
UITableViewController之所以能帮忙,是因为他遵守了<UITableViewDelegate>这个协议。要让某个类遵守某协议,只需要声明的时候在后面尖括号加上协议就可以了,像<UITableViewDelegate>这样
子类继承父类,也继承父类的协议
协议的本质,是一个方法列表,里面的方法还没实现。
协议的方法有2种,@required和@optional
@required是被委托对象一定要实现的方法,@optional则是选择性的,如果没有标记则默认都为@required
三、UITableView常用属性和方法
http://www.cnblogs.com/zhaofucheng1129/p/3754265.html?utm_source=tuicool&utm_medium=referral
感觉都是些满常用的,放着用到的话可以查
四、关于Core Data
入门的一些知识:
http://blog.csdn.net/q199109106q/article/details/8563438/
建立一个基于Core Data的工程,会自动创建3个类的对象
NSManagedObjectModel对象,加载模型文件,管理数据的存储结构文件,读取app中所有的实体信息,扩展名xcdatamodeld
NSPersistentStoreCoordinator对象,管理底层数据的存储(?),可以用很多种方法存储数据,比如SQLite,或者pilst
NSManagedObjectContext对象,把上面俩连在一起,变成整体。所有的CD操作都是用这个类,使用CD的话需要好好看好
还没怎么看过。。看完这部分再补充下
五、字典,数组
TableView显示用的数据一般通过字典与数组来存放
数组NSArray,可变数组NSMutableArray,后者继承自前者,并且有着可以修改里面元素的方法;
同理有字典NSDictionary,可变字典NSMutableDictionary,后者也同样有着可以修改里面元素的方法。
(1)、数组
数组是按照一定【顺序】存储的一系列的【对象】,对象可以是字符串形式的NSString,也可以是字典或者其他,通过知道要取用的对象在数组中的位置便可以取出相应的对象。
初始化(以可变数组作为例子):NSMutableArray *arr = [[NSMutableArray alloc] initWithObejct:@"a",@"b",nil];
这样可以直接在初始化的同时把元素添加进数组,或者之后通过
[arr addObject:@"c"];
这个方法来添加。
另外的几个常用的方法:
移除最后一个元素
removeLastObject:
移除指定位置的元素:
removeObjectAtIndex:
修改指定位置的元素为@"d"
replaceObjectAtIndex: withObject:@"d"
判断数组中是否存在@"x"
[array containsObject:@"x"];
返回一个bool值
(2)字典
NSDictionary在给定的关键字下(通常NSString)存储一个数值(可任意类型对象),可以用这个关键字来查找相应的值,这个关键字称为key
NSMutableDictionary可变字典,允许添加删除字典元素
可使用initWithObjectsAndKeys来创建字典,
NSDictionary *dic = [[NSDictionary alloc]initWithObjectAndKeys:@"obj1",@"key1",@"obj2",@"key2",nil];
使用这种方法时要千万注意object与key的对应,一不小心中间少了一个会造成后面都乱了的
查询字典的值:objectForKey
NSMutableDictionary的dictionary方法可以创建一个可变字典,也可以使用dictionaryWithCapaticy:。
使用 setObject:forkey: 方法添加字典元素,如果关键字已存在,则用新植替换旧值。
类似的,NSMutableDictionary类允许随意添加或删除字典元素。
添加元素:setObject:forkey:
删除元素:removeObjectForKey:
注:字典是存放不了BOOL类型的,可以适当地转换为别的形式进行保存
(3)嵌套使用
一般来说,tableview都会有多个分组的,作为数据源的部分一般采用数组和字典看情况互相嵌套的方式,这样可以解决很多种显示的问题。
根据实际应用来灵活进行嵌套而构成数据源是很重要的
(4)其他补充的
补充一个方法[NSString stringWithFormat:@"%d",i]
某次任务中用到的,将循环计数用的int类型的i,转换为oc的NSString对象,因为i是无法直接存入数组的必须先这样转换
六、重用
UITableView中,因为手机屏幕有限,当内容过多时不可能显示所有内容,于是假设手机能显示的cell数目为n,那么运行时会先开一个内存池,把n+2个(包含刚消失的那个和将要显示的那个,不确定)cell给初始化出来,当有一个cell离开这部分时这个cell会回到内存池并且被下一个将要显示的内容从内存池中拿来使用,这样就可以避免开辟过多的内存造成的浪费。
cell之间是否可以重用通过重用标识符来判断,比如一系列标识符为@“cell”的那这些cell就可以在某个部分被重用
有得时候重用会造成数据的重复显示(大概是存在子视图的情况下?),解决这种情况的方法为:在cell离开屏幕的时候要把数据清空
{
//(只要最后一个显示的cell内容不为空,然后把它的子视图全部删除,等同于把这个cell单独出来了 然后跟新数据就可以解决重复显示)
while ([cell.contentView.subviews lastObject] != nil) {
[(UIView *)[cell.contentView.subviews lastObject] removeFromSuperview];
}
}
在使用accessoryType进行cell的标记的时候发现这种方法并不管用
(我通过创建一个嵌套着字典的数组来显示数据,字典中显示着对应行的数据以及是否被选中)
在滚动时CheckMark会混乱地显示
这时可以通过重写一个cell来解决,通过一个UIImageView来显示勾而代替了使用自带的accessoryType即可解决问题
适当地使用自定义cell可以方便地显示想要的内容
关于定制cell可参考
http://www.cnblogs.com/smileEvday/archive/2012/06/28/tableView.html
http://blog.csdn.net/fanxiaochuan/article/details/11332775
应该还有不少要补充的。。未完待续