We already have two runtime checkers available to us in the form the Address Sanitizer, which allows you to track down rogue memory, and the Thread Sanitizer, which can help you eliminate threading bugs. Apple has gifted us with not one, but TWO additional runtime checkers for the Xcode 9 release.
Main Thread Checker
At some point in our careers we’ve all made some UI change, run our app, and waited with baited breath only to be sad and confused as to why our UI changes aren’t taking effect. After spending some valuable time poking around, we realized that we were calling some UI code from a background thread and the fix was as simple as dispatching to main with a
Apple to the rescue, with the new Main Thread Checker that is enabled by default in Xcode 9! This will detect calls to AppKit or UIKit (basically, anything with a UI at the beginning) from a background thread and throw a warning in the console. The warning will contain information about the offending thread and a backtrace. You can also choose to pause on these warnings by enabling an option in the scheme editor.
How does it work? It prepends a check for any function that should only be called from the main thread. While that might sounds intensive, Apple promises the performance impact of having this checker enabled is minimal (1 - 2% CPU overhead). For those UIKit methods that are specifically designed to be called from a background thread, they will be exempt from the checker. For example, creating instances of
As of the beta, there have been reports of many popular 3rd party libraries triggering these warnings. If you need to disable the checker for the sanity of your console, open the scheme editor for your project:
Navigate to the Diagnostics tab, and uncheck the Main Thread Checker option.
Undefined Behavior Sanitizer
This is a new checker for C languages only (so no Swift support), and will show a nice little purpley warning on any undefined behavior. What constitutes undefined behavior you ask? Quite a lot of interesting things it turns out! It can detect errors like integer overflows, division by zero, out of bounds array access, and much more. See the docs for a complete list.
How does it work? It uses Clang to emit checks into your code during compilation. The nature of the checks can vary depending on what is being checked for, and as such the associated overhead is much higher than the Main Thread Checker (~20% estimated CPU overhead). This is probably the reason this checker is disabled by default.
You can enable it (and probably should for at least a couple run throughs of your app) in the Diagnostics tab of the scheme editor. You can also enable it by compiling and linking your app with the following flag:
clang -fsanitize=undefined xcodebuild -enableUndefinedBehaviorSanitizer YES
Don’t need to check for everything on the list? You can also enable checks for individual items with the compiler flags listed here.