2015-08-11 2 views
35

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

+0

так .. https://github.com/nrbrook/NBUIKitMainThreadGuard – Fattie

+0

Обратитесь к этому [сообщение] (http://stackoverflow.com/q/28302019/ 6521116) –

ответ

66

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

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

Вы, по крайней мере эти 2 варианта:

Асинхронный Сопроводительные

Использование 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]; 

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

+0

, поэтому мы делаем пару обновлений в пользовательском интерфейсе, когда слышим уведомление, так вы говорите, что мне нужно сделать эти обновления внутри «dispatch_async (dispatch_get_main_queue()»? –

+0

Точно. Я добавил примеры. – SwiftArchitect

+0

alrighty, попробовав это сейчас и выберешь свое, как ответ, если он исправил его: D –

3

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

Swift:

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

Obj-C:

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

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

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

Swift 3,0

DispatchQueue.main.async { 
} 
+1

Также работает с Swift 4 –

5

Все UI часть Updation вам нужно перейти в основной поток приложения.

Я был вызов createMenuView() в фоновом режиме, и я получил ниже ошибки

«Это приложение модификации autolayout двигатель от фонового потока, что может привести к повреждению двигателя и странные аварии»

Таким образом я назвал выше метода в основной поток, используя

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

Если попытаться Символическое Breakpoint обнаружить проблему: - enter image description here

Символ:

[UIView layoutIfNeeded]` 

Состояние:

!(BOOL)[NSThread isMainThread] 

Затем поместите ваш UI код Обновить в главном потоке

DispatchQueue.main.async {} 
+0

Отличный ответ, чтобы найти проблематичный кусок кода. Спасибо! –

Смежные вопросы

 Смежные вопросы