- Notifications
You must be signed in to change notification settings - Fork24
A wrapper of NSNotificationCenter to make pub sub easier
License
Glow-Inc/GLPubSub
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
GLPubSub is a wrapper ofNSNotificationCenter
to make pub sub easier. It's a category onNSObject
, so it can be called on any subclass ofNSObject
.
With CocoaPods, you can simply:
- Add following dependency in your
Podfile
:
pod "GLPubSub", "~> 1.0"
- Run
pod install
to install GLPubSub.
If you're not using CocoaPods to manage libraries, you can also import source file directly.
- Downloadlatest code and unzip.
- Import
NSObject+GLPubSub.h
andNSObject+GLPubSub.m
into your project. Remember to tick "Copy items if needed" when importing.
Because GLPubSub is based onNSNotificationCenter
and registered on[NSNotificationCenter defaultCenter]
, system notifications are also supported, e.g.UIApplicationDidEnterBackgroundNotification
,UIApplicationDidBecomeActiveNotification
,UITextFieldTextDidChangeNotification
etc. But you will loseuserInfo
of the notification.
GLPubSub is built on top of-addObserverForName:object:queue:usingBlock:
method ofNSNotificationCenter
. You can set the queue passed into this method by calling+setPubSubQueue:
ofNSObject
.
The PubSub queue isnil
by default, which means event callbacks will be triggered on the queue where the notification is posted. You can explicitly set the queue to[NSOperationQueue maniQueue]
to make all callbacks triggered on main thread.
[NSObjectsetPubSubQueue:[NSOperationQueuemainQueue]];
Most of the time, we useself
as subscriber:
[selfsubscribe:@"YourEventName"selector:@selector(yourEventHandler)];
You can subscribe to event published by some specified object:
[selfsubscribe:@"YourEventName"obj:somePublisherselector:@selector(yourEventHandler)];
If you want your handler only be triggered once, you can use:
[selfsubscribeOnce:@"YourEventName"selector:@selector(yourEventHandler)];
Then after triggered, the event will be automatically unsubscribed.
Your selector can defined accepting one parameter, if so, aGLEvent
object representing the event will be passed into your selector.
@interfaceGLEvent :NSObject@property (nonatomic,copy)NSString *name;@property (nonatomic,retain)id obj;@property (nonatomic,retain)id data;
Where,name
is the event name,obj
is the publisher who triggered the event anddata
is additional data of the event.
All the methods are similar to those above, only with selector replaced by handler block.
GLEventHandler
is defined as:
typedefvoid (^GLEventHandler)(GLEvent *event);
So you can subscribe to some event using syntax like:
__weak__typeof__(self) weakSelf = self;[selfsubscribe:UIApplicationDidEnterBackgroundNotificationhandler:^(GLEvent *event) { __strong__typeof__(weakSelf) strongSelf = weakSelf; [strongSelfappDidEnterBackground];}];
Weakifying self here is important to avoid retain cycle. Corresponding to methods with selector, there're 4 methods can be used with handler block:
- (id)subscribe:(NSString *)eventName handler:(GLEventHandler)handler;- (id)subscribe:(NSString *)eventName obj:(id)obj handler:(GLEventHandler)handler;- (id)subscribeOnce:(NSString *)eventName handler:(GLEventHandler)handler;- (id)subscribeOnce:(NSString *)eventName obj:(id)obj handler:(GLEventHandler)handler;
Unsubscribe one event:
- (void)unsubscribe:(NSString *)eventName;
Unsubscribe all subscribed events:
- (void)unsubscribeAll;
Although the observers will be deallocated when the instance deallocate, it's still recommended to unsubscribe manually, for example in-dealloc
method, or sometimes in-viewDidDisappear
method, according to your requirement.
- (void)dealloc{ [selfunsubscribeAll];}
You can simply publish an event without additional data:
[selfpublish:@"YourEventName"];
or with additional data, most of the time aNSDictionary
object in practice:
[selfpublish:@"YourEventName"data:@{@"key": value}]
Since all observers are retained byself
, there will be retain cycle if your block retainsself
. So you have to weakify self as mentioned above. We highly recommend doing weakify/strongify withEXTScope in libextobjc, with the library, your code would look like:
@weakify(self);[selfsubscribe:UIApplicationDidEnterBackgroundNotificationhandler:^(GLEvent *event) { @strongify(self); [selfappDidEnterBackground];}];
GLPubSub is available under the MIT license. See the LICENSE file for more info.
GLPubSub 是NSNotificationCenter
的封装,目标是简化 iOS 开发中的发布订阅模式。因为是NSObject
的 Category,所以可以在任意NSObject
的子类上使用。
如果通过 CocoaPods 管理第三方依赖,你可以:
- 在
Podfile
里添加以下依赖:
pod "GLPubSub", "~> 1.0"
- 运行
pod install
来安装 GLPubSub
如果你的项目没有用 CocoaPods 来管理第三方依赖,你也可以直接导入源文件。
- 下载最新代码并解压
- 导入
NSObject+GLPubSub.h
和NSObject+GLPubSub.m
到你的工程,记得在导入时勾选 "Copy items if needed"
因为 GLPubSub 是基于NSNotificationCenter
并注册在[NSNotificationCenter defaultCenter]
的,所以 GLPubSub 也支持大部分系统通知,例如UIApplicationDidEnterBackgroundNotification
,UIApplicationDidBecomeActiveNotification
,UITextFieldTextDidChangeNotification
等等,但是转发的过程中会丢弃系统通知的userInfo
字段。
GLPubSub 主要基于NSNotificationCenter
的-addObserverForName:object:queue:usingBlock:
方法。你可以调用NSObject
的+setPubSubQueue:
方法来设置传入该方法的queue
。
默认传入的queue
为nil
,这意味着所有事件会在发布通知的线程中被执行。你可以手动设置为[NSOperationQueue maniQueue]
使得所有事件在主线程被触发:
[NSObjectsetPubSubQueue:[NSOperationQueuemainQueue]];
大部分时候,我们用self
作为订阅者:
[selfsubscribe:@"YourEventName"selector:@selector(yourEventHandler)];
你也可以指定事件的发布者:
[selfsubscribe:@"YourEventName"obj:somePublisherselector:@selector(yourEventHandler)];
如果你希望你的方法只触发一次,你可以用:
[selfsubscribeOnce:@"YourEventName"selector:@selector(yourEventHandler)];
这样当该事件被触发后,就会自动取消订阅。
你的方法可以接受一个GLEvent
参数,该参数包含了被触发事件的相关信息。
@interfaceGLEvent :NSObject@property (nonatomic,copy)NSString *name;@property (nonatomic,retain)id obj;@property (nonatomic,retain)id data;
name
是事件名,obj
是发布者,data
是附加信息。
方法与上面通过 selector 订阅的方法类似:
GLEventHandler
定义如下:
typedefvoid (^GLEventHandler)(GLEvent *event);
所以你可以如下用 block 订阅一个事件:
__weak__typeof__(self) weakSelf = self;[selfsubscribe:UIApplicationDidEnterBackgroundNotificationhandler:^(GLEvent *event) { __strong__typeof__(weakSelf) strongSelf = weakSelf; [strongSelfappDidEnterBackground];}];
这里的 weak 化是为了避免循环引用。对应于前面 selector 的方法,用 block 也有 4 种调用方法:
- (id)subscribe:(NSString *)eventName handler:(GLEventHandler)handler;- (id)subscribe:(NSString *)eventName obj:(id)obj handler:(GLEventHandler)handler;- (id)subscribeOnce:(NSString *)eventName handler:(GLEventHandler)handler;- (id)subscribeOnce:(NSString *)eventName obj:(id)obj handler:(GLEventHandler)handler;
取消订阅某个事件:
- (void)unsubscribe:(NSString *)eventName;
取消订阅所有事件:
- (void)unsubscribeAll;
虽然当实例被销毁时,存在 associated object 中的观察者也都会被销毁,但还是建议手动取消订阅,如根据不同需求,在-dealloc
或-viewDidDisappear
方法中取消订阅。
- (void)dealloc{ [selfunsubscribeAll];}
你可以简单地发布一个事件:
[selfpublish:@"YourEventName"];
也可以附带一些数据,很多时候我们会传入一个NSDictionary
来附带更多结构化的数据:
[selfpublish:@"YourEventName"data:@{@"key": value}]
因为所有生成的观察者都会被self
引用,所以当你的 block 引用self
的时候就会形成循环引用导致实例无法被释放,所以你必须 weakifyself
。强烈推荐用libextobjc 中的 EXTScope 来做 weakify/strongify:
@weakify(self);[selfsubscribe:UIApplicationDidEnterBackgroundNotificationhandler:^(GLEvent *event) { @strongify(self); [selfappDidEnterBackground];}];
GLPubSub 基于 MIT 协议开源,详见 LICENSE 文件。
About
A wrapper of NSNotificationCenter to make pub sub easier