0

I want to swizzle a function in objective-c. The problem is that - I know the function that needs to be swizzled only at runtime. Now different methods in the code will have different return types, input params etc.

How should I write a (generic) code that, if given the name of the function and class to which it belong, I can create a block and then use imp_implementationWithBlock to create IMP and then swizzle original method with this newly created IMP.

prabodhprakash
  • 3,825
  • 24
  • 48

1 Answers1

1

You can use NSSelectorFromString() to dynamically look up a selector name and then perform the swizzling. There are many helpers so I don't need to repeat the exact swizzling logic. E.g. if you use Aspects the code could look like this:

[_singleTapGesture aspect_hookSelector:NSSelectorFromString(@"setState:") withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
    NSLog(@"%@: %@", aspectInfo.instance, aspectInfo.arguments);
} error:NULL];

For runtime-swizzling you should make sure you know what you're doing and fail gracefully if the selector does not exist.

steipete
  • 7,581
  • 5
  • 47
  • 81
  • lets say, I have a function foo which is throwing an exception. I want to surround the body of this function with a try-catch block. Thus, I need to make a block from this function foo and the block must have exactly same signature. This block will have a try-catch between which I will call the original method. After which, I will swizzle the original code to new block. Thus any further calls to foo will go through a try-catch implemented in the block. I am not able to create a block at runtime because, I do not know about its arguments and return type at compile time. – prabodhprakash May 05 '16 at 08:46
  • Aspects provide only before, after and instead - I need to surround it with try-catch, is there a way to do that using Aspects? – prabodhprakash May 05 '16 at 08:51
  • Also, how would this block in example would take the arguments to the function? we need to supply that in usingBlock. – prabodhprakash May 05 '16 at 09:14
  • 1
    You can easily wrap it with using the Instead option and then calling the original implementation - see AspectInfo and the README in the repo. – steipete May 05 '16 at 09:46