此应用程序正在从后台线程修改自动布局引擎,这可能导致引擎损坏和奇怪的崩溃
This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes
当我在 运行 我的应用程序是模拟器时,我在控制台中得到了这个日志。在 iOS 8 中没有看到这个。我不太确定是什么原因造成的。有没有其他人遇到过同样的问题,如果是的话,它是如何解决的?或者有任何人可以提供这方面的帮助吗?
不要从主线程以外的任何地方更改 UI。虽然它似乎可以在某些 OS 或设备上运行而不在其他设备上运行,但它势必会使您的应用程序不稳定,并意外崩溃。
如果您必须响应通知,可以在后台发生,则确保UIKit
调用发生在主线程.
你至少有这两个选项:
异步调度
如果可以在任何线程上通知您的观察者,请使用 GCD
(Grand Central Dispatch)。您可以从任何线程收听和执行工作,并将 UI 更改封装在 dispatch_async
:
中
dispatch_async(dispatch_get_main_queue()) {
// Do UI stuff here
}
什么时候使用GCD
?当您不控制谁发送通知时。它可以是 OS、Cocoapod、嵌入式库等。使用 GCD
将随时随地唤醒。缺点:您发现自己重新安排工作。
在主线程上监听
方便地,您可以指定要在哪个线程上通知观察者,在注册 通知时,使用 queue
参数:
addObserverForName:@"notification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
// Do UI stuff here
}
什么时候在主线程上观察?当你既注册又注册的时候。但是当您回复通知时,您已经到了您需要去的地方。
Post 主线程上的通知
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
不保证仅从所述方法调用观察者的混合解决方案。它允许更轻的观察者,以更不稳健的设计为代价。此处仅作为解决方案提及你应该避免。
您有从后台线程更新 UI 布局的代码。
更改您 运行 您的代码所在的操作队列不需要是显式的。例如 NSURLSession.shared() 在发出新请求时不使用主队列。
为了确保你的代码 运行s 在主线程上,我使用了 NSOperationQueue 的静态方法 mainQueue().
Swift:
NSOperationQueue.mainQueue().addOperationWithBlock(){
//Do UI stuff here
}
Obj-C:
[NSOperationQueue mainQueue] addOperationWithBlock:^{
//Do UI stuff here
}];
我的情况也发生了同样的问题,我必须按以下方式更改代码才能正常工作。
在ViewDidLoad
中,使用main thread
、
调用此方法
[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];
Swift 3.0
DispatchQueue.main.async {
}
您需要将所有 UI 部分更新移至 App 的主线程。
我正在调用 createMenuView() 进入后台,但出现以下错误
"This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes"
所以我使用
将上述方法调用到主线程中
DispatchQueue.main.async {
}
在 SWIFT 3.0 和 Xcode 8.0
中
下面写的正确代码:
RequestAPI.post(postString: postString, url: "https://www.someurl.com") { (succeeded: Bool, msg: String, responceData:AnyObject) -> () in
if(succeeded) {
print(items: "User logged in. Registration is done.")
// Move to the UI thread
DispatchQueue.main.async (execute: { () -> Void in
//Set User's logged in
Util.set_IsUserLoggedIn(state: true)
Util.set_UserData(userData: responceData)
self.appDelegate.createMenuView()
})
}
else {
// Move to the UI thread
DispatchQueue.main.async (execute: { () -> Void in
let alertcontroller = UIAlertController(title: JJS_MESSAGE, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alertcontroller.title = "No Internet"
alertcontroller.message = FAILURE_MESSAGE
self.present(alertcontroller, animated: true, completion: nil)
})
}
}
应该尝试使用符号断点来检测问题:-
符号:
[UIView layoutIfNeeded]
条件:
!(BOOL)[NSThread isMainThread]
然后把你的UI更新代码放到主线程
DispatchQueue.main.async {}
当我在 运行 我的应用程序是模拟器时,我在控制台中得到了这个日志。在 iOS 8 中没有看到这个。我不太确定是什么原因造成的。有没有其他人遇到过同样的问题,如果是的话,它是如何解决的?或者有任何人可以提供这方面的帮助吗?
不要从主线程以外的任何地方更改 UI。虽然它似乎可以在某些 OS 或设备上运行而不在其他设备上运行,但它势必会使您的应用程序不稳定,并意外崩溃。
如果您必须响应通知,可以在后台发生,则确保UIKit
调用发生在主线程.
你至少有这两个选项:
异步调度
如果可以在任何线程上通知您的观察者,请使用 GCD
(Grand Central Dispatch)。您可以从任何线程收听和执行工作,并将 UI 更改封装在 dispatch_async
:
dispatch_async(dispatch_get_main_queue()) {
// Do UI stuff here
}
什么时候使用GCD
?当您不控制谁发送通知时。它可以是 OS、Cocoapod、嵌入式库等。使用 GCD
将随时随地唤醒。缺点:您发现自己重新安排工作。
在主线程上监听
方便地,您可以指定要在哪个线程上通知观察者,在注册 通知时,使用 queue
参数:
addObserverForName:@"notification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
// Do UI stuff here
}
什么时候在主线程上观察?当你既注册又注册的时候。但是当您回复通知时,您已经到了您需要去的地方。
Post 主线程上的通知
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
不保证仅从所述方法调用观察者的混合解决方案。它允许更轻的观察者,以更不稳健的设计为代价。此处仅作为解决方案提及你应该避免。
您有从后台线程更新 UI 布局的代码。 更改您 运行 您的代码所在的操作队列不需要是显式的。例如 NSURLSession.shared() 在发出新请求时不使用主队列。 为了确保你的代码 运行s 在主线程上,我使用了 NSOperationQueue 的静态方法 mainQueue().
Swift:
NSOperationQueue.mainQueue().addOperationWithBlock(){
//Do UI stuff here
}
Obj-C:
[NSOperationQueue mainQueue] addOperationWithBlock:^{
//Do UI stuff here
}];
我的情况也发生了同样的问题,我必须按以下方式更改代码才能正常工作。
在ViewDidLoad
中,使用main thread
、
[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];
Swift 3.0
DispatchQueue.main.async {
}
您需要将所有 UI 部分更新移至 App 的主线程。
我正在调用 createMenuView() 进入后台,但出现以下错误
"This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes"
所以我使用
将上述方法调用到主线程中 DispatchQueue.main.async {
}
在 SWIFT 3.0 和 Xcode 8.0
中下面写的正确代码:
RequestAPI.post(postString: postString, url: "https://www.someurl.com") { (succeeded: Bool, msg: String, responceData:AnyObject) -> () in
if(succeeded) {
print(items: "User logged in. Registration is done.")
// Move to the UI thread
DispatchQueue.main.async (execute: { () -> Void in
//Set User's logged in
Util.set_IsUserLoggedIn(state: true)
Util.set_UserData(userData: responceData)
self.appDelegate.createMenuView()
})
}
else {
// Move to the UI thread
DispatchQueue.main.async (execute: { () -> Void in
let alertcontroller = UIAlertController(title: JJS_MESSAGE, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alertcontroller.title = "No Internet"
alertcontroller.message = FAILURE_MESSAGE
self.present(alertcontroller, animated: true, completion: nil)
})
}
}
应该尝试使用符号断点来检测问题:-
符号:
[UIView layoutIfNeeded]
条件:
!(BOOL)[NSThread isMainThread]
然后把你的UI更新代码放到主线程
DispatchQueue.main.async {}