Last active
December 13, 2018 09:17
-
-
Save ElwinHsiao/aa5a5498d509cdcdca61f57b2484bf3c to your computer and use it in GitHub Desktop.
a objective-c class that bridge CFNotification between NSNotification
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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