Это приложение изменяет механизм автозапуска из фонового потока, что может привести к повреждению двигателя и странным сбоям

Я получаю этот журнал в консоли, когда я запускаю свое приложение в симуляторе. Я не видел этого в iOS 8. Я не совсем уверен, что вызывает это. Кто-нибудь еще сталкивается с той же проблемой, и если да, то как это было исправлено? или есть ли какая-либо помощь, которую кто-либо может предоставить в отношении этого?

Ответ 1

Не меняйте интерфейс из ничего, кроме основного потока. Хотя может показаться, что он работает на некоторых ОС или устройствах, а не на других, он должен сделать ваше приложение неустойчивым и непредсказуемым сбоем.

Если вы ответите на уведомление, которое может произойти в фоновом режиме, убедитесь, что выполняется UIKit.

У вас есть как минимум два варианта:

Асинхронная отправка

Используйте GCD (Grand Central Dispatch), если ваш наблюдатель может быть уведомлен о любом потоке. Вы можете слушать и выполнять работу из любого потока и инкапсулировать изменения пользовательского интерфейса в 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];

Гибридное решение, которое не гарантирует, что наблюдатель только вызывается из указанного метода. Это позволяет более лёгким наблюдателям за счет менее прочной конструкции. Только упоминается здесь как решение, которое вы, вероятно, должны избегать.

Ответ 2

Swift 3.0

DispatchQueue.main.async {
}

Ответ 3

Все обновления части пользовательского интерфейса вам нужно переместить в основной поток приложения.

Я вызывал 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 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

У вас есть код, который обновляет макет пользовательского интерфейса из фонового потока. Изменение очереди операций, в которой выполняется ваш код, не обязательно должно быть явным. Например, NSURLSession.shared() не использует основную очередь при создании новых запросов. Чтобы убедиться, что ваш код работает в основном потоке, я использую статический метод NSOperationQueue mainQueue().

Swift:

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

Obj-C:

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

Ответ 5

Чтобы определить проблему, попробуйте использовать символическую точку останова: -enter image description here

Символ:

[UIView layoutIfNeeded]

Состояние:

!(BOOL)[NSThread isMainThread]

Затем поместите свой код обновления пользовательского интерфейса в основной поток

DispatchQueue.main.async {}

Ответ 6

Такая же проблема возникает в моем случае, я должен изменить код следующим образом, тогда он отлично работает. В ViewDidLoad вызовите этот метод, используя main thread,

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