【问题标题】:This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes此应用程序正在从后台线程修改自动布局引擎,这可能导致引擎损坏和奇怪的崩溃
【发布时间】:2015-11-04 06:21:38
【问题描述】:

当我在模拟器中运行我的应用程序时,我会在控制台中收到此日志。在 iOS 8 中还没有看到这个。我不太确定是什么原因造成的。有没有其他人遇到过同样的问题,如果是这样,它是如何解决的?或者在这方面有人可以提供任何帮助吗?

【问题讨论】:

标签: iphone ios9 xcode7-beta4


【解决方案1】:

应该尝试符号断点来检测问题:-

符号:

[UIView layoutIfNeeded]

条件:

!(BOOL)[NSThread isMainThread]

然后把你的 UI 更新代码放到主线程中

DispatchQueue.main.async {}

【讨论】:

  • 找到有问题的代码的好答案。谢谢!
【解决方案2】:

在我的情况下发生了同样的问题,我必须按照以下方式更改代码然后它才能正常工作。 在ViewDidLoad中,使用main thread调用该方法,

[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];

【讨论】:

    【解决方案3】:

    所有 UI 部分更新都需要移到 App 的主线程中。

    我正在后台调用 createMenuView(),但出现以下错误

    “此应用程序正在从后台线程修改自动布局引擎,这可能导致引擎损坏和奇怪的崩溃”

    所以我将上述方法调用到主线程中使用

        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)
                })
            }
        }
    

    【讨论】:

      【解决方案4】:

      斯威夫特 3.0

      DispatchQueue.main.async {
      }
      

      【讨论】:

        【解决方案5】:

        您有从后台线程更新 UI 布局的代码。 更改运行代码的操作队列不需要明确。例如 NSURLSession.shared() 在发出新请求时不使用主队列。 为了确保您的代码在主线程上运行,我使用了 NSOperationQueue 的静态方法 mainQueue()。

        斯威夫特:

        NSOperationQueue.mainQueue().addOperationWithBlock(){
            //Do UI stuff here
        }
        

        对象-C:

        [NSOperationQueue mainQueue] addOperationWithBlock:^{
            //Do UI stuff here
        }];
        

        【讨论】:

          【解决方案6】:

          不要从主线程以外的任何地方更改 UI。虽然它可能看起来适用于某些操作系统或设备,但不适用于其他操作系统或设备,但它必然会使您的应用程序不稳定,并意外崩溃。

          如果您必须响应通知,而该通知可能在后台发生,请确保UIKit 调用在主线程上进行

          你至少有这两个选择:

          异步调度

          使用GCD (Grand Central Dispatch) 如果您的观察者可以在任何线程上收到通知。您可以从任何线程监听和工作,并将 UI 更改封装在 dispatch_async 中:

          dispatch_async(dispatch_get_main_queue()) {
              // Do UI stuff here
          }
          

          什么时候使用GCD?当您无法控制谁发送通知时。它可以是操作系统、Cocoapod、嵌入式库等。使用GCD 将随时随地唤醒。缺点:您会发现自己重新安排工作。


          监听主线程

          方便地,您可以使用queue 参数指定希望在哪个线程上通知观察者,在您注册通知时

          addObserverForName:@"notification"
              object:nil
              queue:[NSOperationQueue mainQueue]
              usingBlock:^(NSNotification *note){
                  // Do UI stuff here
              }
          

          什么时候在主线程上观察?当您同时注册和注册时。但是,当您响应通知时,您就已经到了需要的地方。


          在主线程上发布通知

          [self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
          

          混合解决方案,不保证仅从所述方法调用观察者。它允许更轻的观察者,但代价是不那么健壮的设计。此处仅作为解决方案提及您可能应该避免

          【讨论】:

          • 所以当我们听到通知时我们会在 UI 上进行一些更新,所以您是说我需要在“dispatch_async(dispatch_get_main_queue()”中进行这些更新吗?
          • 没错。我已经添加了示例。
          • 好吧,现在试试这个,如果它修复它会选择你的作为答案:D
          • 为什么在 iOS 8 中不需要这样做?为什么在 iOS 9 中会发生这种情况?
          • 最好的做法是在 iOS 8 之前 - Apple 刚刚选择 iOS 9 开始警告不正确的更新,并且,正如错误所述,很快将完全禁止后台线程上的 UI 更新。
          猜你喜欢
          • 1970-01-01
          • 2023-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多