Last active
October 16, 2019 19:33
-
-
Save xhruso00/7eedfd1158d4678ed3fc49d9a0ecc060 to your computer and use it in GitHub Desktop.
Magic behind CIFilter modernization (for swift) on macOS 10.15 uses class_addMethod
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 <Cocoa/Cocoa.h> | |
#import <CoreImage/CoreImage.h> | |
@protocol CILineOverlay <CIFilter> | |
@property (nonatomic, retain) CIImage *inputImage; | |
@property (nonatomic) float threshold; | |
@end | |
@interface CIFilter(CILineOverlay) | |
+ (CIFilter<CILineOverlay>*) lineOverlayFilter; | |
@property (nonatomic, retain) CIImage *inputImage; | |
@property (nonatomic) float threshold; //notice that they dropped input keyword | |
@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 <CoreImage/CoreImage.h> | |
#include <objc/runtime.h> | |
@implementation CIFilter(CILineOverlay) | |
@dynamic inputImage; | |
@dynamic threshold; | |
+ (CIFilter<CILineOverlay>*) lineOverlayFilter | |
{ | |
CIFilter<CILineOverlay>*filter = (CIFilter<CILineOverlay>*)[CIFilter filterWithName:@"CILineOverlay"]; | |
static dispatch_once_t oncePredicate; | |
dispatch_once(&oncePredicate, ^{ | |
class_addMethod([self class], @selector(threshold), (IMP)floatGetter, "f@:"); //dynamically add input keyword | |
class_addMethod([self class], @selector(setThreshold:), (IMP)floatSetter, "v@:f"); | |
}); | |
return filter; | |
} | |
static float floatGetter(id self, SEL _cmd) { | |
NSString *selector = NSStringFromSelector(_cmd); | |
NSString *firstLetter = [[selector substringWithRange:NSMakeRange(0, 1)] uppercaseString]; | |
NSString *key = [@"input" stringByAppendingString:[selector stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstLetter]]; | |
/// SEL == threshold | |
/// key == inputThreshold | |
id value = [self valueForKey:key]; | |
float number = NAN; | |
if (value && [value isKindOfClass:[NSNumber class]]) { | |
number = [value floatValue]; | |
} | |
return number; | |
} | |
static void floatSetter(id self, SEL _cmd, float value) { | |
NSString *selector = NSStringFromSelector(_cmd); | |
NSString *key = [selector stringByReplacingCharactersInRange:NSMakeRange(0, 3) withString:@"input"]; | |
/// SEL == setThreshold | |
/// key == inputThreshold | |
[self setValue:@(value) forKey:[key substringWithRange:NSMakeRange(0, [key length] - 1)]]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment