Xcode 8 or 9 started displaying runtime issues. You see a purple icon at the top of the window, and a list in Issue Navigator, next to buildtime issues like compilation warn
Just wanted to add a Swift implementation of a runtimeWarning
method, for anyone curious:
func runtimeWarning(_ message: String) {
// Load the dynamic library.
guard let handle = dlopen(nil, RTLD_NOW) else {
fatalError("Couldn't find dynamic library for runtime warning.")
}
// Get the "__main_thread_checker_on_report" symbol from the handle.
guard let sym = dlsym(handle, "__main_thread_checker_on_report") else {
fatalError("Couldn't find function for runtime warning reporting.")
}
// Cast the symbol to a callable Swift function type.
typealias ReporterFunction = @convention(c) (UnsafePointer<Int8>) -> Void
let reporter = unsafeBitCast(sym, to: ReporterFunction.self)
// Convert the message to a pointer
message.withCString { messagePointer in
// Call the reporter with the acquired messagePointer
reporter(messagePointer)
}
}
It depends on you if you are doing any UI related stuff on other then main thread so system will generate for you else you can not manually generate it.
All UI manipulations should be done in the Main Thread.
If you are not doing this so, in XCode 9 have feature called Main thread checker.
For more info, you can visit below url: https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
It is basically used to checks whether any UIKit
related stuff is happening on a main thread or not ?, If failed to do so, it will produce issues at Runtime. So wrap your code in Main Thread block like below to avoid glitches and runtime warnings.
You can Enable - Disable using this steps Edit Scheme... -> (Select your scheme) -> Diagnostics -> Disable 'Main thread checker'
Yes! You'll see these if you do something that a sanitizer catches, like performing certain UI operations a background thread with Thread Sanitizer enabled. Having an ambiguous layout and pausing in the view debugger is also a way to get this to occur. Either way, seeing this occur in Apple's libraries isn't a good thing…
UPDATE: I looked into how these warnings are hit, and LLDB essentially sets a breakpoint on a set of magic functions (__asan::AsanDie(), __tsan_on_report, __ubsan_on_report, __main_thread_checker_on_report) inside of a sanitizer dynamic library that are called when issues occur. If you define your own version of these functions and call them, you'll get the warning to show up. First, create the symbol somewhere in your project:
void __main_thread_checker_on_report(char *message) {
}
Then you can trigger it at will, just by putting this code anywhere in your application (you probably want to hide it behind a macro):
((void (*)(char *))dlsym(dlopen(NULL, RTLD_LAZY), "__main_thread_checker_on_report")))("This will show up as a warning")
Needless to say, this will almost certainly not play nicely with the actual sanitizer if you choose to use it. You should probably compile the above conditionally based on whether you are using a sanitizer or not.
CocoaLumberjack framework can be used to capture Run times console logs as well as App's Background wakeup logs.
https://github.com/CocoaLumberjack/CocoaLumberjack
https://github.com/phonegap/phonegap-plugin-push/issues/1988
This way you can capture purple warnings displayed in Xcode9 like below in a file that is maintained inside App Container:-
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication registerUserNotificationSettings:] PID: 2897, TID: 1262426, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 21
Well, that's a hack, far from ideal, but can by useful to get runtime warnings without having game-over behavior like in assertions or fatal errors:
func runtimeWarning(_ message: String, file: String = #file, line: Int = #line) {
#if DEBUG
DispatchQueue.global(qos: .userInteractive).async {
// If you got here, please check console for more info
_ = UIApplication.shared.windows
print("Runtime warning: \(message): file \(file.fileName), line \(line)")
}
#endif
}
fileprivate extension String {
var fileName: String { URL(fileURLWithPath: self).lastPathComponent }
}
Unfortunately this leads to quite a big print to console from Main Thread Checker, also does not show on correct line, but at least you have all info needed in console (including line of code you should check).
Usage and result is very similar to assertionFailure
or fatalError
:
runtimeWarning("Hi, I'm purple")
leads to message in console:
Runtime warning: Hi, I'm purple: file MyFile.swift, line 10
and this, so you won't miss it:
In XCode 8.3 and earlier you can use set breakpoint into any method of UIKit class like setNeedsDisplay()
like below.
Also there is library in objective-c steipete class in which #import <objc/runtime.h>
is used.
But in Xcode 9 below library Xcode.app/Contenets/Developer/usr/lib/libMainThreadChecker.dylib
is available, Which handle for any relevant issues potentially performed out-of-main thread at runtime.