Skip to content

Instantly share code, notes, and snippets.

@ElwinHsiao
Last active December 13, 2018 09:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ElwinHsiao/aa5a5498d509cdcdca61f57b2484bf3c to your computer and use it in GitHub Desktop.
Save ElwinHsiao/aa5a5498d509cdcdca61f57b2484bf3c to your computer and use it in GitHub Desktop.
a objective-c class that bridge CFNotification between NSNotification
// DarwinNotificationBridge.h
@interface DarwinNotificationBridge: NSObject
+ (instancetype)startBridgeForTarget:(id)target andSelector:(SEL)selector forName:(NSString *)name;
+ (void) postNotification:(NSString *)name withUserInfo:(NSDictionary *)userInfo;
- (instancetype)initWithTarget:(id)target andSelector:(SEL)selector forName:(NSString *)name;
- (void)start;
- (void)stop;
@end
// DarwinNotificationBridge.m
static void onDarwinNotification(CFNotificationCenterRef center, void *observer,
CFStringRef name, const void *object, CFDictionaryRef userInfo) {
NSDictionary *nsUserInfo = (__bridge_transfer NSDictionary *)userInfo;
id nsObject = (__bridge_transfer id)object;
NSString *nsName = (__bridge_transfer NSString *)name;
NSNotification *noti = [NSNotification notificationWithName:nsName object:nsObject userInfo:nsUserInfo];
DarwinNotificationBridge *receiver = (__bridge DarwinNotificationBridge*)observer;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC*100), dispatch_get_main_queue(), ^{ // it maybe crash if no delay here.
[receiver performSelector:@selector(dispatchNotification:) withObject:noti];
});
}
@implementation DarwinNotificationBridge {
__weak id _target;
SEL _selector;
NSString *_name;
CFTypeRef _cfSelf;
}
+ (instancetype)startBridgeForTarget:(id)target andSelector:(SEL)selector forName:(NSString *)name {
DarwinNotificationBridge *instance = [[self alloc] initWithTarget:target andSelector:selector forName:name];
[instance start];
return instance;
}
- (instancetype)initWithTarget:(id)target andSelector:(SEL)selector forName:(NSString *)name {
self = [super init];
if (self) {
_target = target;
_selector = selector;
_name = name;
}
return self;
}
- (void)start {
if (_cfSelf != NULL) return;
_cfSelf = CFRetain((__bridge void *)self);
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), _cfSelf,
onDarwinNotification, (__bridge_retained CFStringRef)_name,
NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
}
- (void)stop {
if (_cfSelf == NULL) return;
CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(), _cfSelf);
CFRelease(_cfSelf);
_cfSelf = NULL;
}
- (void)dispatchNotification:(NSNotification *)notification {
if ([_target respondsToSelector:_selector]) {
[_target performSelector:_selector withObject:notification];
}
}
+ (void)postNotification:(NSString *)name withUserInfo:(NSDictionary *)userInfo {
CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge_retained CFStringRef)name,
NULL, (__bridge_retained CFDictionaryRef)userInfo, YES);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment