If you've been following me on Twitter or the live streams on Twitch then you may be aware that I've been working on the iOS library for Crash Catch, and you may also be aware that it hasn't been a particularly easy task.
Crash Catch currently supports Android (Java), ReactJS and PHP but before Crash Catch, was my initial attempt, CritiMon. With CritiMon I created crash reporting libraries for the following libraries - these will be ported over to Crash Catch in the not too distant future.
- Android (Java & Kotlin)
- C# (.Net Framework and .Net Core)
All of these languages and frameworks were relatively straightforward and I could get basics working within a few hours, and get the library pretty much completed within a couple of days, even languages I hadn't previously worked with such as Python and Ruby.
Creating the iOS library, unfortunately has not been the same at all, its been weeks, if not more than a month to get this far and I'm not happy with the progress and that I am having to create this post, but here we are.
Unfortunately, although Crash Catch will now support iOS error reports from Swift applications, it will not receive automatic reports for unhandled exceptions, e.g. exceptions that trigger the app to actually crash and shutdown.
I've not previously done any iOS development so I can't 100% guarantee that what I am saying is correct, but from what all of the research and attempts I've made at creating this library, this is what I believe to be the case, however, if there are any experts out there who wants to advice, I'd be more than willing to hear from you.
How does crash reporting work for Crash Catch and iOS
Lets start off with handled errors, e.g. errors that you catch yourself and report if and when you want to such as within try/catch blocks.
iOS and Swift seems to do this very differently compared to other languages that I've dealt with. Every other language I've dealt with the exception is basically a class that extends a base class, e.g. for Java, the base class is called "Exception" and you can have another exception type class such as "Java.lang.NullPointerException". Because each exception class is an extension of "Exception" the exception class, no matter what it is, can be provided to the Crash Catch Library where it can get the exception name (the class name) and the error message, as well as the stack from the exception.
Swift however, doesn't seem to work like this, at least I couldn't find any reference to an exception being part of a base class that I could access, and from looking at how other services do this, this does seem to be the case.
Therefore to report on a handled error, you need to know from your code an error condition where you want to report, this can still be within a try/catch however, but there is no base information from the exception object that Crash Catch can receive. Therefore, you need to create a CCException with the details you want, and then pass this to the library.
However, this doesn't include the stack and this brought a whole other set of issues.
There are methods within Swift, such as you can call Thread.getCallStack(), the issue with this is you get a mangled stack which is basically unreadable to a human, and if you did get a proper crash stack, this would usually just be list of hex addresses and/or mangled stack lines, and the stack would need to go through a symbolication process. In order to do this, you need access to a physical device in order to create an archive, and this creates what's called a dSYM file, and then there's a couple of commands you can use to symbolicate the crash report and return a human readable stack.
This had some issues, one this has to be done from a MacOS PC and the dSYM file would need to be uploaded. This wasn't too much of an issue, I've had to do something similar with ReactJS except there is there alot more information on that, Apple seemed to keep all of this information very secret. The next problem was all of the servers for Crash Catch run Linux, I was considering having to get a MacOS server to do this process, however, there's very little information as to the spec of the dSYM file, plus this process only really works from a crash report by the Apple App store reports, and not by me manually getting the stack programatically.
Thankfully I stumbled upon an open source project on GitHub call RCBacktrace which provides me a demangled stack that I could retrieve and process to give me the information that I need for Crash Catch, such as the class file and the file and the method that triggered the error.
So that was the start of the issues I was having in getting this project done. Next step was unhandled exception reporting.
This is where I hit a massive brick wall. Most languages I've used have some sort of listener that you can register for catching and then handling unhandled exceptions, i.e. exceptions that you have not caught yourself using a try/catch method.
I didn't make much progress in this regard, but this was mostly because finding information as to how this is actually done was next to impossible. Every article I found (and there was several regarding people asking the question about making their own crash reporting service) was just don't do it. Most of them saying its a bad idea, its next to, if not actually impossible to implement correctly, likely not to be able handle certain critical failures.
Due to this, I've made the difficult decision to not implement this specific area and instead, you should rely on the Apple App Store crash reports for unhandled exceptions, but Crash Catch can be used for bugs within your code where you can report on specific issues that you catch yourself within the code.
I want to ensure that Crash Catch, and what is offered is the best that it can be, and yes I know there are other services that claim to be able to report on unhandled exception, and I am only saying claim, because I've not tried it, or know whether it works 100% of the time, therefore I don't want to implement something where its not guaranteed to provide the service that you are expecting.
I hope to revisit this in the future if possible and see what options might be available, but in the meantime, I hope you understand the reasoning behind this and this doesn't put you off from using Crash Catch.
Crash Catch is still currently in beta, and we are offering 50% off the lifetime of your subscription if you sign up, and if you don't like it, you can cancel your account at any time.
You can sign up at https://crashcatch.com.