Last active
August 29, 2015 14:21
-
-
Save zonble/4ae8f44528eaac7ed8ce to your computer and use it in GitHub Desktop.
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
@import Foundation; | |
@interface KKWatchAppNotificationCenter : NSObject | |
+ (instancetype)sharedCenter; | |
- (void)postNotification:(NSString *)key; | |
- (void)addTarget:(id)target selector:(SEL)selector name:(NSString *)notification; | |
- (void)removeObserver:(NSObject *)observer; | |
@end |
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
#import "KKWatchAppNotificationCenter.h" | |
#define LFSuppressPerformSelectorLeakWarning(doPerformSelector) \ | |
do { \ | |
_Pragma("clang diagnostic push") \ | |
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ | |
doPerformSelector; \ | |
_Pragma("clang diagnostic pop") \ | |
} while (0) | |
@interface KKWatchAppNotificationCenter () | |
{ | |
NSMutableDictionary *notificationKeys; | |
} | |
@end | |
@implementation KKWatchAppNotificationCenter | |
+ (instancetype)sharedCenter | |
{ | |
static KKWatchAppNotificationCenter *sharedRegister = nil; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
sharedRegister = [[KKWatchAppNotificationCenter alloc] init]; | |
}); | |
return sharedRegister; | |
} | |
- (instancetype)init | |
{ | |
self = [super init]; | |
if (self) { | |
notificationKeys = [[NSMutableDictionary alloc] init]; | |
} | |
return self; | |
} | |
- (void)postNotificationWithKey:(NSString *)key | |
{ | |
CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); | |
CFDictionaryRef const userInfo = NULL; | |
BOOL const deliverImmediately = YES; | |
CFNotificationCenterPostNotification(center, (CFStringRef)key, NULL, userInfo, deliverImmediately); | |
} | |
- (void)addTarget:(id)target selector:(SEL)selector name:(NSString *)notification | |
{ | |
if (!target) { | |
return; | |
} | |
if (!selector) { | |
return; | |
} | |
if (!notification || ![notification length]) { | |
return; | |
} | |
NSMutableArray *a = [notificationKeys objectForKey:notification]; | |
BOOL needRegisterNotification = NO; | |
if (!a) { | |
a = [NSMutableArray array]; | |
needRegisterNotification = YES; | |
} | |
for (NSDictionary *d in a) { | |
if (d[@"target"] == target && NSSelectorFromString(d[@"selector"]) == selector) { | |
return; | |
} | |
} | |
NSDictionary *d = @{@"target": target, @"selector": NSStringFromSelector(selector)}; | |
[a addObject:d]; | |
if (needRegisterNotification) { | |
[self registerNotification:notification]; | |
[notificationKeys setObject:a forKey:notification]; | |
} | |
} | |
- (void)removeObserver:(NSObject *)observer | |
{ | |
NSMutableArray *notificationsToDelete = [[NSMutableArray alloc] init]; | |
for (NSString *notification in notificationKeys) { | |
NSMutableArray *a = notificationKeys[notification]; | |
NSMutableArray *objectsToDelete = [NSMutableArray array]; | |
for (NSDictionary *d in a) { | |
id target = d[@"target"]; | |
if (target == observer) { | |
[objectsToDelete addObject:d]; | |
} | |
} | |
[a removeObjectsInArray:objectsToDelete]; | |
if (![a count]) { | |
[notificationsToDelete addObject:notification]; | |
} | |
} | |
for (NSString *notification in notificationsToDelete) { | |
[self unregisterNotification:notification]; | |
[notificationKeys removeObjectForKey:notificationKeys]; | |
} | |
} | |
- (void)registerNotification:(NSString *)key | |
{ | |
CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); | |
CFNotificationSuspensionBehavior const suspensionBehavior = CFNotificationSuspensionBehaviorDeliverImmediately; | |
CFNotificationCenterAddObserver(center, (__bridge const void *)(self), KKWatchAppNotificationRegisterCallback, (CFStringRef)key, NULL, suspensionBehavior); | |
} | |
- (void)unregisterNotification:(NSString *)key | |
{ | |
CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); | |
CFNotificationCenterRemoveObserver(center, (__bridge const void *)(self), (CFStringRef)key, NULL); | |
} | |
void KKWatchAppNotificationRegisterCallback(CFNotificationCenterRef center, void * observer, CFStringRef name, void const * object, CFDictionaryRef userInfo) | |
{ | |
KKWatchAppNotificationCenter *self = (__bridge KKWatchAppNotificationCenter *)observer; | |
NSString *notification = (__bridge NSString *)name; | |
NSArray *a = [self->notificationKeys objectForKey:notification]; | |
for (NSDictionary *d in a) { | |
id target = d[@"target"]; | |
SEL action = NSSelectorFromString(d[@"selector"]); | |
LFSuppressPerformSelectorLeakWarning([target performSelector:action withObject:nil]); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment