2012-06-20 3 views
16

So UIView non è thread-safe quindi non posso aggiungere una vista su un thread in background, per ovviare a questo è ok per creare un UIView su un thread in background quindi aggiungerlo sul thread principale?Va bene creare un UIView su un thread in background?

Nota: la ragione im non fare questo sul thread principale è perché il mio codice attuale è molto più complessa e per questo vuole un po 'per creare tutti i punti di vista e riempire i valori. Non voglio che l'interfaccia utente diventi priva di risposta quando lo faccio, quindi sto cercando di aggirare questo problema.

per esempio ..

-(void)addLabel//called on background thread 
{ 
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0,0,40,100)]; 
    [label setText:@"example"] 
    [self.view performSelector:@selector(addSubview:) onThread:[NSThread mainThread] withObject:example waitUntilDone:YES]; 
} 

Grazie in anticipo.

+0

Credo che tu abbia corretto. Crealo sullo sfondo ma aggiorna l'interfaccia utente principale. –

risposta

15

Da UIView:

Considerazioni Threading

manipolazioni deve avvenire nel thread principale interfaccia utente dell'applicazione. Pertanto, dovresti sempre chiamare i metodi della classe UIView dal codice in esecuzione nel thread principale della tua applicazione. L'unica volta che questo non può essere strettamente necessario è quando si crea l'oggetto vista stesso, ma tutte le altre manipolazioni dovrebbero verificarsi sul thread principale.

La chiamata a initWithFrame: non è esplicitamente thread-safe. La chiamata a setText: probabilmente non è thread-safe, rientrando nella clausola "manipolazioni". Questi certamente non sono promessi per essere thread-safe.

fare il vostro lavoro per capire i dati su un thread in background. Quindi crea le tue visualizzazioni sul thread principale. Se il numero di visualizzazioni è elevato, puoi provare a suddividere il lavoro utilizzando più chiamate dispatch_async() nella coda principale. Ciò potrebbe lasciare che l'interfaccia utente rimanga reattiva; Non ho fatto molti esperimenti con esso.

Si consiglia inoltre di passare da UIView a CALayer ove possibile. La maggior parte del lavoro CALayer può essere eseguito sui thread in background. Se hai un numero enorme di visualizzazioni, probabilmente è comunque inefficiente. Se è solo che ci vuole molto tempo per calcolare i dati per le viste, questo suggerisce che non stai separando correttamente le informazioni sul modello e sulla vista. Le classi del modello dovrebbero calcolare tutto ciò che è necessario indipendentemente dalla creazione delle viste.

+5

Mi dispiace ma potresti chiarire la tua risposta ? La citazione di Apple dice chiaramente che creare una vista sullo sfondo va bene, ma stai dicendo che non lo è. Perché? –

+0

@iamataptool probabilmente puoi creare UIView in modo sicuro con il metodo 'init' ma non con il metodo' initWithFrame: '? – DanSkeel

+0

Il consiglio di CALayer ha reso il mio giorno e la mia settimana. Molte grazie! –

0

I Drawing and Printing Guide stati:

Importante Le classi UIKit generalmente non sono thread-safe. Tutte le operazioni relative al disegno devono essere eseguite sul thread principale dell'applicazione.

Quindi, a quanto mi risulta, sembra che l'unico problema sia relativo alle "operazioni relative al disegno". Se supponiamo che una classe corretta esegua tale operazione solo nel suo metodo drawRect:, allora l'approccio che suggerisci dovrebbe andare bene.

+0

Nel mio caso, la mia app si riattiva tramite "UIApplicationLaunchOptionsLocalNotificationKey", quindi è in background. Va bene, se eseguo aggiunte secondarie quando l'app è in background? https://stackoverflow.com/questions/46584566/how-to-stop-handle-ui-operations-in-ios-when-app-moves-to-background-state – Nil

3

Io uso Xcode versione 9.0 beta 3 (9M174d), ricezione di un avviso.

[uview init] deve essere chiamato dal thread principale solo

Quindi penso che si dovrebbe creare interfaccia utente in thread principale migliore

Mostra l'immagine qui sotto:

enter image description here