Skip to content

Instantly share code, notes, and snippets.

@jonsterling
Created July 26, 2010 03:08
Show Gist options
  • Save jonsterling/490132 to your computer and use it in GitHub Desktop.
Save jonsterling/490132 to your computer and use it in GitHub Desktop.
JSProtocolChecker = NSProtocolChecker that works on iOS. Maybe some day I'll find a use for this.
//
// JSProtocolChecker.h
//
// Created by Jon on 7/25/10.
// Copyright (c) 2010 Jonathan Sterling. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface JSProtocolChecker : NSProxy
@property (nonatomic, readonly) NSObject *target;
@property (nonatomic, readonly) Protocol *protocol;
+ protocolCheckerWithTarget:(NSObject *)aTarget protocol:(Protocol *)aProtocol;
+ (Class)protocolCheckerWithClass:(Class)aClass protocol:(Protocol *)aProtocol;
- initWithTarget:(NSObject *)aTarget protocol:(Protocol *)aProtocol;
@end
//
// JSProtocolChecker.m
//
// Created by Jon on 7/25/10.
// Copyright (c) 2010 Jonathan Sterling. All rights reserved.
//
#import "JSProtocolChecker.h"
#import <objc/runtime.h>
#import <objc/Protocol.h>
@implementation JSProtocolChecker
@synthesize target;
@synthesize protocol;
+ protocolCheckerWithTarget:(NSObject *)aTarget protocol:(Protocol *)aProtocol {
return [[[self alloc] initWithTarget:aTarget protocol:aProtocol] autorelease];
}
+ (Class)protocolCheckerWithClass:(Class)aClass protocol:(Protocol *)aProtocol {
return (Class)[[[self alloc] initWithTarget:(id)aClass protocol:aProtocol] autorelease];
}
- initWithTarget:(NSObject *)aTarget protocol:(Protocol *)aProtocol {
self->target = [[aTarget retain] autorelease];
self->protocol = aProtocol;
return self;
}
- forwardingTargetForSelector:(SEL)aSelector {
id ret = nil;
BOOL (^hasMethod)(BOOL,BOOL) = ^(BOOL isRequired, BOOL isInstance) {
typedef struct objc_method_description omd;
uint outCount = 0;
omd *methods = protocol_copyMethodDescriptionList(self.protocol, isRequired, isInstance, &outCount);
BOOL result = NO;
for (int i = 0; i < outCount; i++) {
if (sel_isEqual(aSelector, methods[i].name)){ result = YES; break; }
}
return result;
};
if (hasMethod(YES,YES) || hasMethod(NO,YES) || hasMethod(YES,NO) || hasMethod(NO,NO)) {
ret = self.target;
}
return ret;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [self.target methodSignatureForSelector:aSelector];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment