I am facing the crash
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
I referred to the crash and added the line self.Indicator.stopAnimating() in my code. It runs fine for one or two tests, and it shows the same crash again.
All the UI handling must be done on the main thread instead of the background thread. That's what the crash says.
So move your UI specific code to DispatchQueue.main.async, i.e.
DispatchQueue.main.async {
self?.Indicator.stopAnimating()
}
That stands for all the UI specific changes. Move them to main thread.
Unrelated: use camel-casing for variable names. It must be indicator instead of Indicator.
Related
Ran into an interesting error today and wondering how I can address it or make this code more robust so that my app doesn't crash. 99% of the time this code works fine and does exactly what I want it to do, but 1% of the time it crashes and Xcode just shows an EXC_BAD_ACCESS error.
Off the top of my head, I am thinking that the app is crashing because I am observing a property that really isn't made to be observed. Any suggestions/solutions?
As mentioned in comments, KVO typically does not run on main thread.
So most likely, when your value observation call back is called in Swift, you need to dispatch your assignment to main thread as you're changing a UI property of the View Controller.
Wrap your statement in a dispatch to main thread like so:
DispatchQueue.main.async {
// your code here
}
I have a large application that uses a number of third-party libraries and am now seeing the following error in the logs: "This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes."
From what I have found here on SO, this is probably being caused by a UI element being changed on a background thread, which is triggering the autolayout. Unfortunately, we have so many UI elements being changed by so many different moving parts that I do not know the best way to find the culprit.
Can anyone tell me how can I found out what exactly is triggering the autolayout change from a background thread?
Sometimes it's not a completion block, but anything that is performed in the background.
In my case it was notifications that where sent. I implemented iCloud in my app, which means that when data was edited or added on another device, the other app(s) receive an iCloud update/notification, which triggered an update of the UITableView.
The code to update the UITableView was not done in the MainThread. Adding the code as shown in the comments fixes it.
I get this warning with this code.
I am checking in the background if an update is available. And then present an alert.
Obviously Xcode and iOS don't like my thinking... any ideas?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
if CheckAppUpdate().appUpdateAvailable("http://itunes.apple.com/lookup?id=xxxxxxxxxxxxx") == true {
self.showAlertForUpdate()
}
})
In iOS all UI code must run on the main thread. You are dispatching to a background thread in order to perform your update check, which is fine, but then trying to update the UI from that same background thread, which is causing the error you are seeing. The solution is to add another dispatch_async inside the first one, wrapping the call to self.showAlertForUpdate(), but dispatching to the main queue (dispatch_get_main_queue(...) instead.
My app runs fine in iOS6, but in an unspecified upcoming version of iOS that I cannot name for NDA reasons, all UIViewController transition animations stop working. New views just pop into place instantly. I am not sure if this unspecified future version of iOS is the cause, as I've seen this happen occasionally in iOS6.
Sometimes animations start working for a while and then stop shortly after, making me think it's some sort of memory warning issue, but my app is using a fairly reasonable ~125MB of RAM at most times. Can anyone offer any advice or things to investigate?
The described behavior has always existed: if you do work on background threads and then call and UIKit methods then more often than not the update will be delayed in a weird way.
Because of this you should always dispatch_async onto the main queue to update the UI.
Those bugs are very hard to catch since they do not always occur predictably.
To catch them I built a method that swizzles some UIKit methods to check if they are called on the main thread. This allows you to stop on a symbolic breakpoint, whenever you have forgotten to dispatch back onto main queue.
https://github.com/Cocoanetics/DTFoundation/blob/develop/Core/Source/iOS/Debug/UIView%2BDTDebug.m
A good workaround from the Apple dev forums on this issue:
Do this:
[UIView setAnimationsEnabled:YES]
And animations start working again. I suspect that this is either a straight up iOS7 bug, or somewhere in my code an animation or UIViewController launch is happening on a background thread, causing animations to stop. Probably unrelated to the unspecified future version of iOS.
This issue appears to be caused by doing UIKit stuff in background threads. I have a pre-render cache full of NSOperations that renders complex UIViews to UIImages to cache the output. This seemed to work fine in iOS6, but probably does cross the line somewhat. I'll need to replace this functionality with something that renders images and text to a graphics buffer rather than using UIViews and UILabels at all.
All you have to do is catch hold of main queue while updating UI on receiving response from an API.Ios uses main queue by default for updating UI but it is not 100 percent efficient.Hence you have to make sure that the UI gets updated on main thread only and the way to do that is as below:
DispatchQueue.main.async{
//UI related code eg:
self.label.text = "abc"
self.button.setTitle("xyz",.normal)
self.tableView.reloadData()
}
If you are not catching hold of main thread animations may or may not work.
But if you are using main thread animations will definetely work.
Correct Code while updating UI on api response:
Alamofire.getApiCall(paramaters: parameters, completion:{
response in
// UI related code.
DispatchQueue.main.async{
self.label.text = "abc"
self.button.setTitle("xyz",.normal)
self.tableView.reloadData()
}
})
Incorrect Code which may cause animations to stop and lead to weird crashes:
Alamofire.getApiCall(paramaters: parameters, completion:{
response in
// UI related code.
self.label.text = "abc"
self.button.setTitle("xyz",.normal)
self.tableView.reloadData()
})
I am doing one application in which i got one HTML string in background thread. I want to load the webview using that HTML string in background.
If I load that web view on background, the app crashes. I don't want to load webview using main thread because on that i don't want to disturb the main thread. And i did the R&D in internet i got one possibility using GCD.I think that one also involved in main thread. SO please let me know how to update the UI in background.
You can not. UI must always be updated from the main thread. Whatever your reason for not wanting to do it from the main thread, that reason is invalid.
No. You cant update UI in other thread then main.