本章内容主要讲述OC语言中常用的开发模式,开发模式是解决某些具体问题的固定解决方案。在OC中主要由三种可以使用
在开发过程中,经常有一些共享型的数据需要储存在一个公共的地方,需要的时候,可以方便回去。单例模式便提供创建一个公共地方的方法。
@interface TestObj: NSObject
@property double a;
@end
例如我们声明上文中的一个对象,其中有一个a的属性可以存储数据。
TestObj * obj1 = [[TestObj alloc] init];
TestObj * obj2 = [[TestObj alloc] init];
obj1.a = 1;
obj2.a = 2;
上文中,通过两个对象指针访问a属性,是两块完全不同的内存空间,所有,两个对象储存的值也没有任何关联。但如果a是一个共享型的数据,那么在代码的任何地方获取的对象指针,应该都必须指向同一块内存,这样才能保证,通过任意对象指针获取的数据都是同一个数据。
解决以上问题,我们需要对类进行单例改造,添加一个单例方法,通过单例方法获取的对象指针都会指向全局唯一的内存。
@interface TestObj: NSObject
@property double a;
+(instancetype)shareTestObj;
@end
单例方法为加号方法,通常以share
+类目的方式进行命名。
@implementation TestObj
+(instancetype)shareTestObj
{
static TestObj * obj = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
obj = [[TestObj alloc] init];
});
return obj;
}
@end
单例方法的实现也十分简单,首先声明一个静态对象指针,保证这个对象指针不会被释放。然后调用GCD中的只运行一次的方法,确保在任何情况下只会开辟一块内存空间,然后将对象指针的值返回。
TestObj * obj1 = [TestObj shareTestObj];
TestObj * obj2 = [TestObj shareTestObj];
经过处理的类具有单例方法,通过单例方法获取的对象指针所指向的内存为同一块内存,这样,在任何一个地方,只需要调用单例方法,便可以获取共享数据。
OC中提供一个键值观察的机制,让我们可以主动观察某一个对象的属性变化情况。
NSObject类支持键值观察机制,所有其子类创建的对象也同时支持。使用兼职观察需要两步
注册观察者与观察路径为NSObject提供的一个方法
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
这个方法需要被观察的对象调用,用来为自己添加其他观察者
方法参数
当被观察对象的属性发生变化时,将会回调一个固定的方法,且此方法不需要被注册,默认生效
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
通过此回调方法,可以反馈到观察者如下信息
下面通过一个完整的案例来展现一下键值观察的模式
@interface Student : NSObject
@property(strong, nonatomic) NSString * name;
@end
@interface Teacher : NSObject
@property(strong, nonatomic) Student * stu;
@end
@implementation Teacher
-(void)test
{
self.stu = [[Student alloc] init];
[self.stu addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
self.stu.name = @"test";
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"%@",change);
}
-(void)dealloc
{
[self.stu removeObserver:self forKeyPath:@"name"];
}
@end
main()
{
Teacher * tea = [[Teacher alloc] init];
[tea test];
}
运行上述代码,即可看到输出结果,当stu对象的name属性发生改变是,键值观察回调方法变会被调用,同时输出change中的信息。
同时需要注意的是,在dealloc方法中移动要移除观察者,否则在对象是否之后,再产生的键值观察回调将会发送给一个野指针,产生概率性崩溃信息。
消息模式是OC中较为特殊的一种开发模式,它为两个不能相见但有需要互通消息的对象提供了一个传递信息的机制。
通常我们在使用回调或者键值观察时,都需要直接获取要产生回调事件的组件对象或需要观察的对象。
但在一些特殊情况,例如之后的App开发课程中需要对键盘对象进行监控,但缺无法获取键盘对象,因键盘对象只在用户触发响应事件是才被创建。这样我们便可以采用消息的方式,接收键盘对象发出来的消息,从而实现对键盘对象行为的监控。
使用消息开发模式需要掌握一下三个步骤
获取消息中心:
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
消息中心对象需要通过单例模式获取,不能进行alloc操作,因为全局必须保证只有一个消息中心,才能够将消息正确的传递。
订阅消息:
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
该方法为消息中心对象的方法,其参数分别为
取消订阅:
- (void)removeObserver:(id)observer;
在dealloc方法中需要消息中心对象调用此方法取消订阅
发送消息分为两步,第一步是创建消息,第二步是发送消息
NSNotification * noti = [NSNotification notificationWithName:@"test" object:self userInfo:@{@"key":@"value"}];
创建一条消息需要三个参数
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
NSNotification * noti = [NSNotification notificationWithName:@"test" object:self userInfo:@{@"key":@"value"}];
[center postNotification:noti];
发送消息是消息中心的功能,调用相应的发送方法,即可把一个消息发送出去,如果在此之前,有对象订阅了相同名称的消息,那么该对象的消息回调方法会被调用。
原文地址:http://blog.csdn.net/yangbingbinga/article/details/46314961