Changing UI from a background thread - ios

I getting an error that Iam changing the autolayout engine from a background thread , is there's a way to know which block of code makes this warning ? or I just have to search for it by myself ??
Thank you.

Probably there is a better answer but I would start by putting
for Swift:
assert(NSThread.isMainThread(), "Expected code to be called on main thread");
for Objective-C:
NSAssert([NSThread isMainThread], #"Expected code to be called on main thread");
to all sections of your code you're suspicious about.
This way app will crash if you're doing that code not on main thread.
Is this error an error or is it an exception? If it is exception you can try to catch it using exception breakpoint like here: How to debug “Collection was mutated while being enumerated” errors and like, when Xcode does not provide me with enough information? ?
After having looked at your exact message looks like what you need is:
This code PSPDFUIKitMainThreadGuard causes assertions on UIKit access outside the main thread
taken from iOS9 - This application is modifying the autolayout engine from a background thread — where?.

Related

iOS app is crashing on ios 13 and with Xcode 11 when it didn't before

Our app is crashing with the fatal exception:
Fatal Exception: NSInternalInconsistencyException
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
Our app used to not throw this exception on previous versions of iOS (12 and below) and when I would compile on Xcode 10. Now, on iOS 13.3.1 and compiling on Xcode 11.3.1 our app crashes 10 seconds after opening every time. I looked into this exception and it seems Apple has decided to prevent apps from accessing the UIKit on background threads (please correct me if I'm wrong here). After enabling the Main Thread Checker I was able to pinpoint the line that was causing this crash. Backtracing the code led me to this line:
dispatch_async(dispatch_get_main_queue(), ^{
//Code that uses the StoreKit to retrieve purchase data,
//then updates the UI using UIKit based on this information
});
This code is fine though right? Because even though it's dispatching this block of code, it's doing it to the main thread, so this shouldn't be the issue, correct? Well, even after moving this block of code out of the dispatch_async() function, it still crashes. So then I looked at the singleton for this class, which looks like this:
+(instancetype)sharedPurchaseManager
{
static PurchaseManager * sharedPurchaseManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPurchaseManager = [[PurchaseManager alloc] _init];
});
return sharedPurchaseManager;
}
And I wondered if the _init() for the PurchaseManager was happening in a background thread. So I tried moving the allocation for PurchaseManager out of the dispatch_once() block and the app stopped crashing. Furthermore, the Main Thread Checker stopped interrupting the program at the line that uses UIKit. I'm pretty sure that moving my _init() code out of the dispatch_once() block is not the correct way to go about fixing my issue, as this is the standard singleton design pattern (please correct me if I'm wrong). So then how should I go about fixing this issue? Furthermore, we have about 10+ crashes in our code that is due to the same exception, and with a similar design pattern to our PurchaseManager, so we would want a solution for all of these exceptions.
It sounds like [[PurchaseManager alloc] _init] contains some UI code, but +(instancetype)sharedPurchaseManager is accessed first time from background thread.
So you can try two approaches:
1) find the way explicitly initialize sharedPurchaseManger on the main thread (eg. in applicationDidFinishLaunching)
2) try to use the following
dispatch_once(&onceToken, ^{
dispatch_sync(dispatch_get_main_queue(), ^{ // << intentionally synchronous!
sharedPurchaseManager = [[PurchaseManager alloc] _init];
}
});

print - Background or main thread operation

This might sound quite basic and stupid but it has been bothering me for a while. How can print be classified in terms of operation - main or background ?
As a small test, on putting print in a background task - web service call :
Webservice().loadHeadlinesForSource(source: source) { headlines in
print("background print")
self.headlineViewModels = headlines.map(HeadlineViewModel.init)
DispatchQueue.main.async {
print("main thread print")
completion()
}
}
Both the print statements get printed. From previous experience, if print was a main thread task, Xcode would have given me a warning saying that I need to put that in main thread. This is an evidence that print is not a main thread operation. Note that I am not saying print is a background task.
However, I have this understanding that since print displays output on Console, it is not a background operation. As a matter of fact all logging operations are not.
How would one justify the classification ?
It seems what you consider to be a main thread operation is a call that needs to be performed on the main thread. From that perspective you are correct and have found an evidence of this call not being a main thread operation.
But does this have anything to do with anything else? Internally if needed this method may still execute its real operation on the main thread or any other thread for what we care. So in this sense a main thread operation is a restriction that call needs to be performed on main thread but has nothing to do with its execution or multithreading.
Without looking into what print does in terms of coding we can see that it works across multiple "computers". You can run your app on your device (iPhone) while plugged and Xcode on your computer will print out logs. This makes a suspicion that print is much like call to the remote server in which case the server is responsible for serializing the events so it makes no difference what thread the client is on. There are other possibilities such as dropping logs into file and then sending it which really makes little difference.
So How can print be classified in terms of operation - main or background? The answer is probably none. The call is not restricted to any thread so it is not main. It will probably lock whatever thread it is on until the operation is complete so it is not background either. Think of it like Data(contentsOf: <#T##URL#>) which will block the thread until data from given URL is retrieved (or exception is thrown).

-[UIApplication delegate] must be called from main thread only

This warning leads to a serious problem cause I really can't call the delegate outside of the main thread using Xcode 9 beta 2. Strange thing is that this was working when I was using Xcode 8.3.3.
Also I thought it would only be good practice to call delegates from main thread only, isn't it? So why is this causing the app to crash now?
Just call it from the main thread like this.
Objective-C
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication delegate] fooBar];
});
Swift
DispatchQueue.main.async {
YourUIControlMethod()
}
Reaching out to your app delegate like this, is a hint that your architecture could use a little cleanup.
You can call delegates from any thread you want. You only need to make sure you're on the main thread for UIKit calls.
Or that you're on the correct thread your CoreData objects expect. It all depends on the API contract your objects have.
In Swift, you could also use DispatchQueue.main.async to call the UI controlling method from the main thread
DispatchQueue.main.async {
YourUIControlMethod()
}

how to continue debug when a crash happened in xcode

My code crashed, and the following line gets highlighted in red. But some crash handle function should continue. How can i debug this crash handle function:
NSSetUncaughtExceptionHandler(&HandleException);
The error that you're generating doesn't result in an Objective-C exception, so exception handlers aren't going to be invoked for it.
If you're trying to test exception handling, you should replace your method code with a throw. If you're trying to test for handling of that specific code, you should create a signal handler for the error that's cut off by your screen shot. (SIGABRT, SIGSEGV, ...?)

Do not stop test execution on XCTAssertThrowsSpecific

Using XCTest, a test does the following:
XCTAssertThrowsSpecificNamed([does something that breaks], NSException, NSInvalidArgumentException);
I don't want the debugger to stop on the NSException that I know will occur but I want it to still stop on other exceptions that might occur.
Basically we don't have a choice. I still consider it an xCode bug because you already told xCode an exception will be thrown, and what exception it will be. Why provide XCTAssertThrows if it's an exception you're not "expecting"?
Obviously it's for exceptions you are expecting, which #nhgrif argues should be an error, not an exception. Might be a good point, but i do want my program to crash if this case ever happens, because I can't handle it.
So the real question is more why not disable the debugger on that exception only? Probably because they haven't gotten around to it. I'd suggest opening a bug/feature request with Apple. I'd love for someone to contradict me on this (please comment!) but until then, I'll live with this issue (disable debugger when running all my tests).
--> https://stackoverflow.com/a/22393643/1701430
"Why does the test stop when the execution is thrown?"
Because you have a breakpoint, which stops execution.
"Why, after removing the breakpoint, does my application crash when the exception is thrown?"
Because you have an unhandled exception. Unhandled exceptions cause your program to crash.
"How can I handle an exception so it won't crash my program?"
The easy answer to this question is to simply NOT throw an exception. In other programming languages, like Java, this is perfectly standard. But in Objective-C, we don't really do exceptions. In Objective-C, exceptions should be saved for TRULY exceptional behavior.
With that said, and a strong suggestion for you to find another way to handle whatever it is you're trying to handle, this is how you handle an exception in Objective-C:
#try {
// code that could throw an exception
}
#catch (NSException *e) {
// handle the exception...
}
#finally {
// post try-catch code, executed every time
}

Resources