Apple released the stable version of Xcode 9 recently with loads of new features. Most iOS developers are saying Xcode 9 is the best release so far as it has great new features that iOS developers always wanted. You can read more about the Xcode 9 features here.
We have just migrated our existing XCUITest suite to Xcode 9 and found that unit tests written in XCTest passed, but the XCUITests stopped working with the following error.
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate] PID: 740, TID: 51958, Thread name: (none), Queue name: FIRAnalyticsQueue, QoS: 9
The XCUITests couldn't launch the proxy test runner app at all and test suite crashed. From the error message, its obvious that it's something related to Firebase SDK and something called Main Thread Checker. Some of you might already fall into this trap, or you will soon as you migrate to Xcode 9. In this post, we will discuss what is this error is all about and how new Xcode featured Main Thread Checker will help to catch potential bugs in the application.
What Is Main Thread Checker?
Before we dive into the error, we will learn what Main Thread Checker is and why Apple introduced this tool as part of Xcode 9. As per the documentation, "Main Thread Checker Detects invalid use of AppKit, UIKit, and other APIs from a background thread." What does this mean? An iOS developer can easily understand this, but for others, I will try to explain in simple language.
There are some Apple frameworks designed to use in iOS apps only in the main thread; using those frameworks in the background thread is a sin. In short, using those frameworks in the background thread will do bad things to your iOS app. Main Thread Checker finds such invalid usage of frameworks and warns an engineer at runtime not to commit this sin. It detects the culprit so that you can punish them if they don't fix it. Main Thread Checker is the handy tool to detect bugs in the code as soon as possible. It's activated by default in the Xcode 9.
An Error in XCUITest
XCUITest launches the proxy test runner app called XCUIApplication to start the tests in the proxy app. The Main Thread Checker was active for the XCUITest for the respective scheme. While launching a UI for the app, Main Thread Checker detected that Firebase SDK has used UP APIs in the background thread. There was the issue open on Github here, which was fixed by the Firebase team.
There might be some other third party frameworks that might have same issue, e.g. Flurry users, who also reported the same issue on Github here, but it's still not fixed at the time of writing this post.
How to Fix XCUITests
There are a few ways we can fix the issue and get going with XCUITests in Xcode 9.
- We can fix the XCUITests by fixing the issue of invalid usage of iOS frameworks if the issue is inside the app.
- If the Main Thread Checker detects an issue that's in a third-party framework like Firebase SDK, we need to get them to fix the issues immediately.
- If the Main Thread Checker detects an issue that's in the third-party framework and they can't fix the issue on time, then, unfortunately, we need to disable the Main Thread Checker from the scheme. Go to Product > Scheme > Manage Schemes and search the Scheme you use for your tests and press Edit... in the left sidebar, press Test and then go to Diagnostics and uncheck the Main Thread Checker checkbox.
Remember, this isn't the ideal solution, this is the hack that we shouldn't be putting in our code. We should focus on fixing the issues directly in the code that causing the invalid use of frameworks.
I hope you will find this post useful when you stuck into the same problem and save a few hours of investigation. Have you migrated your XCUITests to Xcode 9? What are your experiences? Let me know in the comments.