Skip to content

Instantly share code, notes, and snippets.

@rustle
Created September 16, 2012 22:54
Show Gist options
  • Save rustle/3734726 to your computer and use it in GitHub Desktop.
Save rustle/3734726 to your computer and use it in GitHub Desktop.
//
// NSNotificationCenter+RSLAdditions.h
//
// Created by Doug Russell
// Copyright (c) 2012 Doug Russell. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import <Foundation/Foundation.h>
@interface NSNotificationCenter (RSLAdditions)
- (id)rsl_addObserver:(id)observer selector:(SEL)selector name:(NSString *)name object:(id)object;
@end
//
// NSNotificationCenter+RSLAdditions.m
//
// Created by Doug Russell
// Copyright (c) 2012 Doug Russell. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "NSNotificationCenter+RSLAdditions.h"
#import <objc/runtime.h>
@protocol RSLObserverWatcherDelegate <NSObject>
- (void)rsl_shouldRemoveObserver:(id)observer;
@end
@interface RSLObserverWatcher : NSObject
@property (weak) id<RSLObserverWatcherDelegate> delegate;
@property id observer;
@end
@interface NSNotificationCenter (RSLObserverWatcherDelegate) <RSLObserverWatcherDelegate>
@end
@implementation NSNotificationCenter (RSLAdditions)
- (id)rsl_addObserver:(id)observer selector:(SEL)selector name:(NSString *)name object:(id)object
{
NSMethodSignature *signature = [observer methodSignatureForSelector:selector];
if (signature == nil)
{
NSLog(@"%@ is an invalid selector", NSStringFromSelector(selector));
return nil;
}
bool validSelector = false;
NSUInteger argCount = [signature numberOfArguments];
if (argCount == 2)
{
// - (void)foo;
validSelector = true;
}
else if (argCount == 3)
{
// - (void)foo:(NSNotification *)note;
validSelector = true;
}
if (!validSelector)
{
NSLog(@"%@ is an invalid notification selector", NSStringFromSelector(selector));
return nil;
}
__weak id weakObserver = observer;
id token = [self addObserverForName:name object:object queue:nil usingBlock:^(NSNotification *note) {
id strongObserver = weakObserver;
if (strongObserver)
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:strongObserver];
[invocation setSelector:selector];
if (argCount == 3)
[invocation setArgument:&note atIndex:2];
[invocation invoke];
}
}];
RSLObserverWatcher *watcher = [RSLObserverWatcher new];
watcher.delegate = self;
watcher.observer = token;
static const void * key = @"RSLObserverWatcher";
objc_setAssociatedObject(observer, key, watcher, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return token;
}
@end
@implementation RSLObserverWatcher
- (void)dealloc
{
[self.delegate rsl_shouldRemoveObserver:self.observer];
}
@end
@implementation NSNotificationCenter (RSLObserverWatcherDelegate)
- (void)rsl_shouldRemoveObserver:(id)observer
{
NSLog(@"%@ %@ %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), observer);
[self removeObserver:observer];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment