年轻的时候要多看点东西,时间是非常宝贵的,不要浪费生命在无所谓的事情上,共勉
1.异常使用的场景是 当程序发生非常严重崩溃的时候。在错误不是那么严重的情况下,可以指派"委托方法"来处理错误对象,或者也可以吧错误信息放在NSERROR对象中,经过"输出参数"返回给调用者
- 假如想让自己所写的对象具有拷贝功能,那么需要实现NSCopying协议。
- 如果自己写的对象同时分为可变版本与不可变版本,那么就需要同时实现NSCopying协议与NSMutableCopying协议。
- 执行对象拷贝的时候需要考虑应该是深拷贝还是浅拷贝,但是大多数情况下应该使用浅拷贝。
3.对象之间经常需要相互通信,而通信方式有很多。OC开发者广泛使用一种名叫“委托模式”(Delegate Pattern)的编程设计模式来实现对象间的通信,该模式的主旨是:定义一套接口,某对象若想接收另一个对象的委托,则需遵从此接口,以便称为“委托对象”(delegate)。而这“另一个对象”则可以给其委托对象回传一些信息,也可以在发生相关联时间时通知委托对象。
此模式可以将数据与业务逻辑解耦。在Objective-C中,一般通过“协议”这项语言特性来实现此模式,整个Coco系统框架都是这么做的。如果你的代买也这样写,那么就能和系统框架很好地融合在一起了。
利用协议机制,很容易就以Objective-C代码实现此模式,代码如下:
@protocol EOCNetworkFetcherDelegate
-(void)netWorkFetcher:(EOCNetworkFetcher*)fetcher didReceiveData:(NSData*)data;//这个EOCNetworkFetcher*参数可以高速委托对象,是谁调用它的
-(void)netWorkFetcher:(EOCNetworkFetcher*)fetcher didFailWithData:(NSError*)error;
@end
有了这个协议之后,类就可以用一个属性来存储委托对象了。在本例中,这个类就是EOCNetworkFetcher类:
@interface EOCNetworkFetcher :NSObject
@property (nonatomic,weak) id delegate;
@end
为了避免循环引用,NetWorkFetcher不保留delegate属性.
看一下EOCDataModel的实现:
NSData *data = /*data obtained from network*/
if([_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]){
[_delegate networkFetcher:self didReceiveData:data];
}
通过这个例子,大家应该很容易理解此模式为何叫做“委托模式”:因为对象把应对某个行为的责任委托给另外一个类了。
关于运行时刻,每次都判断respondsToSelector:@selector(xxxx)是多余的,只有第一次判断是有用的。参考优化办法
【本节要点】
● 委托模式为对象提供了一套接口,使其可由此相关事件告知其他对象。
● 将委托对象应该支持的接口定义成协议,在协议中把可能需要处理的事情定义成方法
● 当某对象需从另一个对象中获取数据时,可以使用委托模式。这种情境下,该模式亦称为“数据源协议”(data source protocal)
● 若有必要,可实现还有位段的结构体,将委托对象是否能够相应相关协议方法这一信息缓存至其中。
4.记住一条原则就可以了,如果一个类方法太多,可以将这些方法按照功能拆分成多个文件。每个文件可以看作是原来类的一个分类。如果想隐藏一个方法的实现,那就可以在分类中实现一个方法,但是不在主类的头文件中声明即可。
5.在使用分类的时候,如果要扩展系统的方法或者给第三方类添加方法,需要给创建的对象方法名字前面添加前缀,这样可以避免命名冲突。保证方法调用的正确性。
6.苹果是建议不要再分类中添加属性,因为对象属性的ivarsize再编译阶段大小就是确定的。但是不排除一些特定业务场景下面,确实需要添加一些属性,这样可以使用关联对象来做,前面也提到过,不做叙述。
7.主要讲的是扩展的概念,也叫做匿名的分类。扩展(EXTENSION)不能单独创建一个文件,他是依附在要扩展的主类的.m文件中的。扩展的主要功能有:
- 向原有的类中新增一个实例变量
- 如果想让一个变量对外只读,对内可读可写,可以再.h文件中声明为readonly,在.m文件中设置为readwrite。
- 再扩展中声明一个私有的方法
- 或者隐藏这个类实现的协议
总得来说,类扩展主要是一个私有变量,私有方法,隐藏类信息的地方
8.通过协议来提供匿名对象。
协议定义了一系列方法,遵从此协议的对象应该实现它们。于是,我们可以用协议把自己写的API之中的实现细节隐藏起来,将返回的对象涉及位遵从此协议的纯id类型。这样的话,想要隐藏的类名就不会出现在API之中了。
此概念经常称为:“匿名对象”(anonymous object),这与其他语言的“匿名对象”不同。
@property (nonatomic,weak)id
由于该属性的类型是id
NSDictionary也能实际说明这一概念,在字典中,键的标准内存管理语义是“设置时拷贝”,而值的语义是“设置时保留”。因此在可变版本的字典中,设置键值对所用的方法的签名是:
-(void) setObject:(id)object forKey:(id)key;
表示键的哪个参数类型位id,作为参数值的对象,它可以是任意类型,只要遵从NSCopying协议就好,这样的话,就能向该对象发送拷贝消息了。这个key参数可以视为匿名对象。与delegate一样
数据案例,数据库连接(database connection)的程序也用这个思路,以匿名对象来表示从另一个库中返回的对象。对于处理连接哪个类,你也许不想让万人知道。如果没有办法令其继承字同一个基类,那么就得返回对下你跟遵从此协议:
@protocol EOCDatabaseConnection
-(void) connect;
-(void)disconnect;
-(void)isConnected;
-(NSArray*)performQuery:(NSString*)query;
@end;
然后,就可以用“数据库处理器”单例来提供数据库连接了。这个单例的接口可以写成
@protocol EOCDatabaseConnection
@interface EOCDatabaseManger:NSObject
+(id)sharedInstance;
-(id) connectionWithIdentifier:(NSString*)identifier;
@end;
这样的话,处理数据库连接所用的类名称几UI不会泄露了。
有时对象类型并不重要,重要的是对象有没有实现某些方法。在次情况下,也可以是使用“匿名类型”(anonymous type)来表达这一概念。
CoreData框架里也有这种用法。查询CoreData数据库所得的结果由名叫NSFetchedResultsContrller的类来处理,如果有需要,处理时还会把数据分区。在负责处理查询结果的控制器中,有个section属性,用以表示数据分区。此属性是个数组,但其中的对像没有指明具体类型,只是说这些对象遵从了NSFetchedResultsSectionInfo协议。下面代码通过控制器来获取数据分区信息:
NSFetchedResultsController * controller = /*some controller*/;
NSUInteger section = /*section index to query*/
NSArray *sections = controller.sections;
id sectionInfo = sections[section];
NSUInteger numberOfObjects = sectionInfo.numberOfObjects;
sectionInfo 是个匿名对象。
【本节要点】
● 协议可在某种程度上提供匿名类型。具体的对象类型可以淡化成遵从某协议的id类型,协议里规定了对象所应实现的方法。
● 使用匿名对象来隐藏类型名称(或类名)
● 如果居室类型不重要,重要的是对象能够响应特定方法,那么可以是使用匿名对象来表示。
9.自动引用计数。没什么可说的,摘抄一下总结
- 引用计数机制通过递增或者递减的计数器来管理内存。对象创建好之后,其保留计数至少为1。假如保留计数为正,那么对象会继续存活。当保留计数降到0的时候,对象被销毁
- 在对象的声明周期中,其余对象通过引用来保留或者释放对象。保留与释放的操作分别会递增或者递减保留计数
10.没什么可讲的 主要说的是ARC做的一些事情,替我们手动插入 retain release autorelease等等