Ho questo registro nella console quando sto eseguendo la mia applicazione in è simulatore. Non ho visto questo in iOS 8. Non sono abbastanza sicuro che cosa sta causando questo. Qualcun altro ha riscontrato lo stesso problema e, in caso affermativo, come è stato risolto? o c'è qualche aiuto che qualcuno può fornire in merito a questo?Questa applicazione sta modificando il motore di autolayout da un thread in background, che può portare a corruzione del motore e crash anomali
risposta
Non modificare l'interfaccia utente da qualsiasi argomento tranne il thread principale. Sebbene possa sembrare che funzioni su alcuni SO o dispositivi e non su altri, è destinato a rendere instabile la tua applicazione e a bloccarsi in modo imprevedibile.
Se si deve rispondere a una notifica, che può accadere in background, quindi garantire UIKit
invocazione si svolge sul thread principale.
avere almeno queste 2 opzioni:
Asynchronous dispatch
Usa GCD
(Grand Central Dispatch) se il vostro osservatore può essere notificata in qualsiasi thread. È possibile ascoltare e fare il lavoro da qualsiasi thread, e incapsulare le modifiche dell'interfaccia utente in un dispatch_async
:
dispatch_async(dispatch_get_main_queue()) {
// Do UI stuff here
}
Quando usare GCD
? Quando non controlli chi invia la notifica. Può essere il SO, un Cocoapod, librerie incorporate, ecc. L'uso di GCD
si sveglierà in qualsiasi momento, ogni volta. Lato negativo: ti ritrovi a riprogrammare il lavoro.
ascolto su Main Thread
comoda, è possibile specificare su quale thread si desidera l'osservatore da notificare, al momento si sta registrando per le notifiche, utilizzando il parametro queue
:
addObserverForName:@"notification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
// Do UI stuff here
}
Quando su osservare sulla filettatura principale? Quando ti stai registrando e registrato. Bu il tempo in cui rispondi alla notifica, sei già dove devi essere.
messaggio di notifica sul filetto principale
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
soluzione ibrida, che non garantisce che l'osservatore è richiamato solo da detto metodo. Permette un osservatore più leggero, al costo di un design meno robusto. Solo menzionato qui come soluzione dovresti probabilmente evitare.
quindi facciamo un paio di aggiornamenti sull'interfaccia utente quando sentiamo una notifica, quindi stai dicendo che ho bisogno di fare quegli aggiornamenti all'interno di "dispatch_async (dispatch_get_main_queue()"? –
Esattamente. Ho aggiunto degli esempi. – SwiftArchitect
potente, prova questo ora e sceglierà il tuo come risposta se lo risolve: D –
Si dispone di codice che aggiorna il layout dell'interfaccia utente da un thread in background. Non è necessario che la modifica della coda di operazioni su cui viene eseguito il codice sia esplicita. Ad esempio NSURLSession.shared() non utilizza la coda principale quando si effettuano nuove richieste. Per garantire che il codice venga eseguito sul thread principale, sto utilizzando il metodo statico mainQueue() di NSOperationQueue.
Swift:
NSOperationQueue.mainQueue().addOperationWithBlock(){
//Do UI stuff here
}
Obj-C:
[NSOperationQueue mainQueue] addOperationWithBlock:^{
//Do UI stuff here
}];
Lo stesso problema è accaduto nel mio caso, devo cambiare il codice in modo seguente poi funziona benissimo. In ViewDidLoad
, chiamano questo metodo utilizzando main thread
,
[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];
Swift 3,0
DispatchQueue.main.async {
}
Funziona anche con Swift 4 –
Tutti UI parte updation è necessario spostare in thread principale di App.
stavo chiamando un createMenuView() in background e ho ottenuto sotto l'errore
"Questa applicazione sta modificando il motore di layout automatico da un thread in background, che può portare alla corruzione del motore e arresti strani"
Così ho chiamato metodo di cui sopra in discussione principali Uso
DispatchQueue.main.async {
}
in SWIFT 3.0 e Xcode 8.0
codice corretto scritto sotto:
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)
})
}
}
dovrebbe cercare Breakpoint simbolico di rilevare il problema: -
Simbolo:
[UIView layoutIfNeeded]`
Condizione:
!(BOOL)[NSThread isMainThread]
Quindi inserire il codice di aggiornamento dell'interfaccia utente nel thread principale
DispatchQueue.main.async {}
Ottima risposta per trovare il pezzo di codice problematico. Grazie! –
così .. https://github.com/nrbrook/NBUIKitMainThreadGuard – Fattie
Fare riferimento a questo [post] (http://stackoverflow.com/q/28302019/ 6521116) –