Created
December 20, 2011 21:04
-
-
Save iamleeg/1503268 to your computer and use it in GitHub Desktop.
Use one selector to provide many methods with similar implementations.
This file contains hidden or 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/Foundation.h> | |
#import <objc/runtime.h> | |
@interface FZAUIElement : NSObject | |
- (id)initWithAXUIElement: (AXUIElementRef)anElement; | |
- (BOOL)press: (NSError *__autoreleasing*)error; | |
- (BOOL)cancel: (NSError *__autoreleasing*)error; | |
@end | |
extern NSString const *FZAUIElementErrorDomain; | |
@interface FZAUIElement () | |
BOOL doTheThing(id self, SEL _cmd, NSError * __autoreleasing *error); | |
+ (CFStringRef)actionForSelector: (SEL)selector; | |
+ (BOOL)hasActionForSelector: (SEL)selector; | |
- (AXUIElementRef)element; | |
@end | |
static NSDictionary *actionSelectorMap; | |
@implementation FZAUIElement | |
{ | |
AXUIElementRef element; | |
} | |
+ (void)initialize { | |
actionSelectorMap = [NSDictionary dictionaryWithObjectsAndKeys: | |
(__bridge id)kAXPressAction, | |
@"press:", | |
(__bridge id)kAXCancelAction, | |
@"cancel:", | |
nil]; | |
} | |
- (id)initWithAXUIElement:(AXUIElementRef)anElement { | |
self = [super init]; | |
if (self) { | |
CFRetain(anElement); | |
element = anElement; | |
} | |
return self; | |
} | |
- (void)dealloc { | |
if (element) { | |
CFRelease(element); | |
} | |
} | |
+ (BOOL)resolveInstanceMethod:(SEL)sel { | |
if ([self hasActionForSelector: sel]) { | |
class_addMethod(self, sel, (IMP)doTheThing, "c@:@"); | |
return YES; | |
} | |
else { | |
return [super resolveInstanceMethod: sel]; | |
} | |
} | |
BOOL doTheThing(id self, SEL _cmd, NSError *__autoreleasing *error) { | |
CFStringRef action = [[self class] actionForSelector: _cmd]; | |
AXError returnCode = AXUIElementPerformAction([self element], action); | |
if (returnCode == kAXErrorSuccess) { | |
return YES; | |
} else { | |
if (error) { | |
*error = [NSError errorWithDomain: (NSString *)FZAUIElementErrorDomain code: returnCode userInfo: nil]; | |
} | |
return NO; | |
} | |
} | |
+ (CFStringRef)actionForSelector:(SEL)selector { | |
NSString *selectorName = NSStringFromSelector(selector); | |
return (__bridge CFStringRef)[actionSelectorMap objectForKey: selectorName]; | |
} | |
+ (BOOL)hasActionForSelector:(SEL)selector { | |
return ([actionSelectorMap objectForKey: NSStringFromSelector(selector)] != nil); | |
} | |
- (AXUIElementRef)element { | |
return element; | |
} | |
@end | |
NSString const *FZAUIElementErrorDomain = @"FZAUIElementErrorDomain"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment