0

I have a number of classes and inside class there are a number of methods defined. I need to perform a specific set of operations when each of these methods getting called. I can write the set of operations in each of the methods. But i don't want to mess up the code. So I have created a helper class, inside that I will pass the set of Classes and Selectors.

I have looped through the array and I used the swizzling technique and exchanged the implementation of each method with a custom method defined in the helper class. So whenever any of the method inside any of the above class triggered, I will get a call to my custom swizzling method.

But my problem is I am not able to distinguish which is the original method triggered. Based on that some of the parameter will change in the custom set of operations I mentioned above.

My current implementation is like the below:

for i in 0..<classes.count {
   let eachClass:AnyClass = classes[i] as AnyClass
   let eachSelector:Selector = selectors[i] as Selector
   let swizzilableClass = MyHelper.self
   let originalMethod = class_getInstanceMethod(eachClass, eachSelector)
   let swizzledMethod = class_getInstanceMethod(swizzilableClass, #selector(MyHelper.trackMethodInvocation))

   method_exchangeImplementations(originalMethod, swizzledMethod)

}

And the currensponding swizzled method is:

func trackMethodInvocation() -> Void {

}

So whenever any of the methods listed in the selectors array is called, the method trackMethodInvocation() will trigger, but I need to know the original selector inside the trackMethodInvocation().

Is there any way to know which is the original method inside the swizzled method.

Bhavin Ramani
  • 3,221
  • 5
  • 30
  • 41
Sreekanth
  • 71
  • 1
  • 4
  • This all sounds like it will be a convoluted maintenance nightmare. Are you sure this is necessary? Btw, use `classes.indices` rather than `0.. – Alexander Nov 18 '16 at 04:38
  • So what my main intention is just a try. There are a couple of analytics tools I need to add to the project to track different button actions. So I am just trying to find is there any way to avoid the analytics related code from IBActions, and a way to identify each IBAction triggers so I can add the analytics code to that methods and leave the IBAction with the button action related code. – Sreekanth Nov 18 '16 at 04:45

1 Answers1

1

So somewhat I have found an alternative solution. Please note that * I will make sure the safety before going with live implementation. There won't be any more loops. What I will do is, I will swizzle the UIApplication's sendAction method with my custom method. And inside my custom method I will do my operations and will call the original sendAction method. So the code will now look like below,

    let originalClass:AnyClass = UIApplication.self
    let swizzilableClass = MyHelper.self

    let originalMethod = class_getInstanceMethod(originalClass, #selector(UIApplication.sendAction(_:to:from:for:)))
    let swizzledMethod = class_getInstanceMethod(swizzilableClass, #selector(MyHelper.trackMethodInvocation(_:to:from:for:)))
    method_exchangeImplementations(originalMethod, swizzledMethod)

And my swizzled method will look like,

func trackMethodInvocation(_ action: Selector, to target: Any?, from sender: Any?, for event: UIEvent?) -> Void {

}

So here I will get the selector. So anyone who trying this, ***please make sure the safety in swizzling UIApplication method. Make sure to call the original method inside the swizzled method. Currently I am doing this for a research purpose only.

Sreekanth
  • 71
  • 1
  • 4