Skip to content

Instantly share code, notes, and snippets.

@michaelochs
Last active February 6, 2022 14:47
Show Gist options
  • Save michaelochs/42256e190d3d230f7f24052159dceb0b to your computer and use it in GitHub Desktop.
Save michaelochs/42256e190d3d230f7f24052159dceb0b to your computer and use it in GitHub Desktop.
As a follow up for https://gist.github.com/michaelochs/f106b5c42aafe6bed74ac5dab82281c4 this is what's going on under the hood!
@interface MyStringProxy : NSProxy
@property (nonatomic) NSString *target;
@end
@implementation MyStringProxy
- (BOOL)respondsToSelector:(SEL)aSelector {
if (aSelector == NSSelectorFromString(@"_dynamicContextEvaluation:patternString:")) {
return YES;
} else {
return [self.target respondsToSelector:aSelector];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
- (NSString *)_dynamicContextEvaluation:(NSString *)context patternString:(NSString *)pattern {
// Do a FORWARD search as it seems the same pattern is used for all the replacements, one by one.
// So we are looking for the first appearance of `pattern` and return our replacement. The next
// placeholder will see the partially replaced string and again looks for the first appearance of
// `pattern` and so on...
NSRange range = [context rangeOfString:pattern];
if (range.location == 0) {
return [NSString stringWithFormat:@"First(%@)", self.target];
} else if (range.location + range.length == context.length) {
return [NSString stringWithFormat:@"last(%@)", self.target];
} else {
return [NSString stringWithFormat:@"middle(%@)", self.target];
}
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MyStringProxy *proxy = [MyStringProxy alloc];
proxy.target = @"something";
NSString *test = [NSString stringWithFormat:@"%@ %@ %@", proxy, proxy, proxy];
NSLog(@"%@", test); // "First(something) middle(something) last(something)"
return YES;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment