Skip to content

Instantly share code, notes, and snippets.

@macguru
Last active January 6, 2018 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macguru/d3a4e21db29e587aab0b3e1def256782 to your computer and use it in GitHub Desktop.
Save macguru/d3a4e21db29e587aab0b3e1def256782 to your computer and use it in GitHub Desktop.
Swizzling behaviour into TISmartPunctuationController
@implementation SwizzlingTextView /* Subclass of UITextView */
{
BOOL _swizzled;
}
/* working solution */
- (void)setInputDelegate:(id<UITextInputDelegate>)inputDelegate
{
[super setInputDelegate: inputDelegate];
if (_swizzled) return;
_swizzled = YES;
id smartPunctuationController = [(id)inputDelegate valueForKey: @"smartPunctuationController"];
SEL selector = NSSelectorFromString(@"smartPunctuationOutputForInput:isLockedInput:documentState:");
Class class = [smartPunctuationController class];
Class subclass = objc_allocateClassPair(class, @"MySmartPunctuationController".UTF8String, 0);
Method method = class_getInstanceMethod(class, selector);
IMP superImp = method_getImplementation(method);
id (^block)(id, NSString*, BOOL, id) = ^id (id self, NSString *inputString, BOOL isLocked, id documentState) {
id result = ((id (*)(id, SEL, NSString*, BOOL, id))superImp)(self, selector, inputString, isLocked, documentState);
/* magic */
return result;
};
class_addMethod(subclass, selector, imp_implementationWithBlock(block), method_getTypeEncoding(method));
objc_registerClassPair(subclass);
object_setClass(smartPunctuationController, subclass);
}
@end
@implementation SwizzlingTextView2 /* Subclass of UITextView */
{
BOOL _swizzled;
}
/* PARTIALLY NOT working solution */
- (void)setInputDelegate:(id<UITextInputDelegate>)inputDelegate
{
[super setInputDelegate: inputDelegate];
if (_swizzled) return;
_swizzled = YES;
id smartPunctuationController = [(id)inputDelegate valueForKey: @"smartPunctuationController"];
[smartsuperPunctuationController swizzleMethod:self.class.smartPunctuationOutputSelector withReplacement:MZMethodReplacementProviderBlock {
return MZMethodReplacement(id, id, NSString *inputString, BOOL isLockedInput, id documentState) {
id result = MZOriginalImplementation(id, inputString, isLockedInput, documentState);
/* magic */
return result;
};
}];
}
@end
@macguru
Copy link
Author

macguru commented Jan 6, 2018

Please note both examples are simplified. The first solution is just fine. The second solution is much more concise, thanks to MZMethodSwizzler.h.

HOWEVER, the second solution suffers from the problem that it's not working in debug builds on device. It's fine in both debug and release in simulator, also fine in release on device. Only debug -O0 seems to fail. The super implementation's behaviour is different. One way to observe this particular example: The text replacement -- for no longer works in this situation, while it's fine in all other cases. Replacement for " always becomes but never , e.g. on word ends.

Any advice?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment