Incomprehensible Crashes? Swizzling method to the rescue!

Reinier Melian Massip
eDreams ODIGEO
Published in
5 min readJul 21, 2022

--

Photo by Philip Swinburn on Unsplash

What is the hardest thing while fixing a crash?, Of course everyone will answer “Find the root cause”

As an iOS developer, for sure you can remember one of THOSE crashes were you was ready to give up, or you try and try different solutions because you don’t know what is the root cause or you don’t have any information that may lead to reproduce or even know what is going on?. I have been there, and I think that almost every iOS Dev has been there before.

In this article I will introduce you to another tool that will help you in the analysis of those crashes that makes our lives miserable 😅.

Method Swizzling Definition

There are many definitions in internet I will stick to this one from NSHipster(1)

Method swizzling is the process of changing the implementation of an existing selector. It’s a technique made possible by the fact that method invocations in Objective-C can be changed at runtime, by changing how selectors are mapped to underlying functions in a class’s dispatch table.

Using method swizzling for crash analysis.

Ok, that’s fine but how we can use it for crashes?. Let start with a use case. We have this report in our Crash reporter tool, in this case Firebase, this is a UIKit call stack only crash

UIKit crash call stack trace

Any Ideas?

Well to be fair, we know that a view can’t add self as Subview. We also know that this crash is triggered by UINavigationController. Maybe a viewController is being pushed 2 or more times in the navigation stack?, is possible. But where should we start to search in a big application were high number of ViewControllers are continuously pushed and pop?. How do we know which viewController(s) are involved or under which circumstances is this happening?. Remember we only have this information from crash report.

Lets put some relevant log info in this crash using method swizzling

We can see here that in call stack trace line 14 we have a private method being called which is involved in the transition process and therefore the crash caused. Would be interesting to log the viewControllers stack of this UINavigationController right?. Or even under which launch conditions our Application is working.

But first be sure this is the method you need to swizzle. We can add a Xcode symbolic break point for that checking when is this function being called. Check that our Symbol name in Symbolic Breakpoint is equal to call stack trace line 14 symbol.

Then enable your new symbolic breakpoint. You now can test transitions between viewControllers handled by UINavigationController. This symbolic breakpoint should be triggered

Swizzling UINavigationController private method

We need to create an extension for UINavigationController and implement our swizzling method there.

Step by step code explanation

1- Ensure this swizzling code is executed only once

2- Get selectors to be switched

3- Ensuring that we have those selectors implemented in our instance. We get those implementations in originalMethod and swizzledMethod

4- Log if something wrong has happened

5- Exchange the implementation of both selectors

After calling this function method_exchangeImplementations the implementations of -[UINavigationController startCustomTransition:] and [UINavigationController swizzled_startCustomTransition:] get swapped. It means that an invocation to originalMethod actually executes the code inside swizzledMethod and vice versa.

6- New swizzled method implementation. This new implementation logs stack of viewControllers and launch info

7- Invoking original -[UINavigationController startCustomTransition:]

Ok but, you are invoking same swizzled_startCustomTransition are you sure you are invoking correct selector?. Yes as we say before when we invoke swizzled_startCustomTransition we are actually invoking the non swizzled method because we have swapped their implementations in step 5

One Image worth more than 1000 words…

UINavigationController startCustomTransition invoked with swizzled selector name

⚠️ Make sure you test your app and this swizzled method is executed correctly without any crash on it before releasing.

How we use it

We can use it in AppDelegate

After release

What we will be seeing in our Firebase reports after release?. Our report has changed, even we have the same crash as new one? 🤔. Don’t worry your swizzling is not creating a new crash 😜.

Now in logs tab we have more info about our crash (the info that we are adding in our swizzling method)

With this new information we now know that MyTripsHomeViewController is causing this crash. Because is being pushed 2 times or more, and now we have a better understanding of what is going on here. Even we can try to reproduce it.

Conclusion

Method Swizzling is a very powerful tool provided by the Objective-C runtime. There are many applications for it, one of them is this one. Helping to understand hard to understand crashes.

If you like it, and find this useful, please hit the clap button below 👏 to help others find it!.

References:

(1) https://nshipster.com/method-swizzling/#:~:text=Method%20swizzling%20is%20the%20process,in%20a%20class's%20dispatch%20table.

(2) https://medium.com/a-swift-journey/method-swizzling-swift-2f281aae189b

(3) https://medium.com/rocknnull/ios-to-swizzle-or-not-to-swizzle-f8b0ed4a1ce6

(4) https://www.innominds.com/blog/method-swizzling-in-ios-development

--

--

Reinier Melian Massip
eDreams ODIGEO

iOS Software Engineer at Edreams Odigeo, Swift, Objective-C