簡體   English   中英

此應用程序正在從后台線程修改自動布局引擎,這可能導致引擎損壞和怪異的崩潰

[英]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 (大中央調度) 您可以從任何線程偵聽和執行工作,並將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];

不能保證僅從所述方法調用觀察者的混合解決方案。 它允許更輕的觀察者,但代價是不那么堅固。 在這里僅提及您可能應該避免的解決方案。

斯威夫特3.0

DispatchQueue.main.async {
}

您需要將所有UI部分更新移至App的MAIN線程中。

我在后台調用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)
            })
        }
    }

您具有從后台線程更新UI布局的代碼。 無需明確更改運行代碼的操作隊列。 例如,NSURLSession.shared()在發出新請求時不使用主隊列。 為了確保您的代碼在主線程上運行,我使用了NSOperationQueue的靜態方法mainQueue()。

迅速:

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

對象:

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

應該嘗試使用符號斷點來檢測問題: 在此處輸入圖片說明

符號:

[UIView layoutIfNeeded]

條件:

!(BOOL)[NSThread isMainThread]

然后將您的UI更新代碼放入主線程

DispatchQueue.main.async {}

我的情況也一樣,我必須按照以下方式更改代碼,然后才能正常工作。 ViewDidLoad ,使用main thread調用此方法,

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM