Skip to content

Instantly share code, notes, and snippets.

@hosokawa0825
Last active August 29, 2015 13:57
Show Gist options
  • Save hosokawa0825/9501951 to your computer and use it in GitHub Desktop.
Save hosokawa0825/9501951 to your computer and use it in GitHub Desktop.
Customizable Responder Chain Category
#import "NSObject+CustomMethod.h"
typedef void(^SelectorBlock)(NSObject *responder);
@implementation NSObject (CustomMethod)
#pragma mark associative storage
- (NSObject *)spi_nextResponder
{
NSObject *ao = objc_getAssociatedObject(self, _cmd);
if (ao) {
return ao;
} else if ([self isKindOfClass:[UIResponder class]] && [self performSelector:@selector(nextResponder)] != nil) {
return [self performSelector:@selector(nextResponder)];
} else if ([self isKindOfClass:[UIViewController class]] && [self performSelector:@selector(parentViewController)] != nil) {
return [self performSelector:@selector(parentViewController)];
} else if ([self isKindOfClass:[UIView class]] && [self performSelector:@selector(superview)] != nil) {
return [self performSelector:@selector(superview)];
} else {
return nil;
}
}
- (void)setSpi_nextResponder:(NSObject *)spi_nextResponder
{
objc_setAssociatedObject(self, @selector(spi_nextResponder), spi_nextResponder, OBJC_ASSOCIATION_ASSIGN);
}
#pragma mark responder chain delegate
// performSelectorのメモリリークについての警告が出るが、これについてはAppleが無視してよいと回答しているため、無視する
// 参考:http://ameblo.jp/xcc/entry-11076019667.html
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- (void)spi_delegateSelector:(SEL)selector withObject:(NSObject *)object1 withObject:(NSObject *)object2
{
[self spi_delegateSelector:selector selectorBlock:^(NSObject *responder) {
[responder performSelector:selector withObject:object1 withObject:object2];
}];
}
- (void)spi_delegateSelector:(SEL)selector withObject:(NSObject *)object
{
[self spi_delegateSelector:selector selectorBlock:^(NSObject *responder) {
[responder performSelector:selector withObject:object];
}];
}
- (void)spi_delegateSelector:(SEL)selector
{
[self spi_delegateSelector:selector selectorBlock:^(NSObject *responder) {
[responder performSelector:selector];
}];
}
#pragma clang diagnostic pop
- (void)spi_delegateSelector:(SEL)selector selectorBlock:(SelectorBlock)selectorBlock {
NSObject *responder;
responder = [self spi_nextResponder];
// nextResponderを辿ってセレクタが実装されているコントローラが見つかったら
// そのコントローラに処理させる。
while (responder) {
if ([responder respondsToSelector:selector]) {
selectorBlock(responder);
break;
}
responder = [responder spi_nextResponder];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment