NSDefaultRunLoopMode vs NSRunLoopCommonModes


114

Ogni volta che provo a scaricare un grosso dietro file di UIScrollView, MPMapViewo qualcosa del genere, il processo di download viene interrotto non appena mi tocco schermo di iPhone. Per fortuna, un fantastico post sul blog di Jörn suggerisce un'opzione alternativa, usando NSRunLoopCommonModesper la connessione.

Questo mi fa esaminare in dettaglio le due modalità, NSDefaultRunLoopMode e NSRunLoopCommonModes, ma il documento Apple non spiega gentilmente, a parte il dire

NSDefaultRunLoopMode

La modalità per gestire sorgenti di input diverse dagli oggetti NSConnection. Questa è la modalità run-loop più comunemente usata.

NSRunLoopCommonModes

Gli oggetti aggiunti a un ciclo di esecuzione utilizzando questo valore come modalità sono monitorati da tutte le modalità di ciclo di esecuzione che sono state dichiarate come membri del set di modalità "comuni"; vedere la descrizione di CFRunLoopAddCommonMode per i dettagli.

CFRunLoopAddCommonMode

Fonti, timer e osservatori vengono registrati in una o più modalità di ciclo di esecuzione e vengono eseguiti solo quando il ciclo di esecuzione è in esecuzione in una di queste modalità. Le modalità comuni sono un insieme di modalità di ciclo di esecuzione per le quali è possibile definire un insieme di sorgenti, timer e osservatori condivisi da queste modalità. Invece di registrare una sorgente, ad esempio, in ciascuna modalità di ciclo di esecuzione specifica, è possibile registrarla una volta nella pseudo-modalità comune del ciclo di esecuzione e verrà automaticamente registrata in ciascuna modalità di ciclo di esecuzione nel set di modalità comune. Allo stesso modo, quando una modalità viene aggiunta alla serie di modalità comuni, eventuali sorgenti, timer o osservatori già registrati nella pseudo modalità comune vengono aggiunte alla modalità comune appena aggiunta.

Qualcuno può spiegare i due in linguaggio umano?

Risposte:


204

Un ciclo di esecuzione è un meccanismo che consente al sistema di riattivare thread inattivi in ​​modo che possano gestire eventi asincroni. Normalmente quando esegui un thread (con l'eccezione del thread principale) c'è un'opzione per avviare il thread in un ciclo di esecuzione o meno. Se il thread esegue un'operazione di ordinamento o di lunga durata senza interazione con eventi esterni e senza timer, non è necessario un ciclo di esecuzione, ma se il thread deve rispondere agli eventi in arrivo, dovrebbe essere collegato a un ciclo di esecuzione per risveglia il filo quando arrivano nuovi eventi. Questo è il caso dei NSURLConnectionthread generati, poiché si riattivano solo su eventi in arrivo (dalla rete).

Ogni thread può essere associato a più cicli di esecuzione o può essere associato a un ciclo di esecuzione specifico che può essere impostato per funzionare in diverse modalità. Una "modalità ciclo di esecuzione" è una convenzione utilizzata dal sistema operativo per stabilire alcune regole su quando consegnare determinati eventi o raccoglierli per essere consegnati in seguito.

Di solito tutti i cicli di esecuzione sono impostati sulla "modalità predefinita" che stabilisce un modo predefinito per gestire gli eventi di input. Ad esempio: non appena si verifica un evento di trascinamento del mouse (Mac OS) o tocco (su iOS), la modalità per questo ciclo di esecuzione viene impostata su monitoraggio eventi; questo significa che il thread non verrà riattivato su nuovi eventi di rete ma questi eventi verranno consegnati in seguito quando l'evento di input dell'utente termina e il ciclo di esecuzione impostato nuovamente sulla modalità predefinita; ovviamente questa è una scelta fatta dagli architetti del sistema operativo per dare priorità agli eventi utente invece che agli eventi in background.

Se si decide di modificare la modalità ciclo di esecuzione per il NSURLConnectionthread, utilizzando scheduleInRunLoop:forModes:, è possibile assegnare il thread a una modalità ciclo di esecuzione speciale , piuttosto che al ciclo di esecuzione predefinito specifico. La speciale pseudo-modalità chiamata NSRunLoopCommonModesviene utilizzata da molte sorgenti di input, incluso il monitoraggio degli eventi. Ad esempio, assegnare NSURLConnectionl'istanza di alla modalità comune significa associare i suoi eventi alla "modalità di tracciamento" oltre alla "modalità predefinita". Un vantaggio / svantaggio dell'associazione di thread con NSRunLoopCommonModesè che il thread non verrà bloccato da eventi di tocco.

Nuove modalità possono essere aggiunte alle modalità comuni, ma questa è un'operazione di livello piuttosto basso.

Vorrei chiudere aggiungendo alcune note:

  • In genere è necessario utilizzare una serie di immagini o miniature scaricate dalla rete con una vista tabella. Potremmo pensare che scaricare queste immagini dalla rete mentre la vista tabella è in scorrimento potrebbe migliorare l'esperienza dell'utente (dato che potremmo vedere le immagini durante lo scorrimento), ma questo non è vantaggioso poiché la fluidità dello scorrimento può risentirne notevolmente. In questo esempio con NSURLConnectionun ciclo di esecuzione non dovrebbe essere utilizzato; sarebbe meglio utilizzare i UIScrollViewmetodi delegato per rilevare quando lo scorrimento è terminato e quindi aggiornare la tabella e scaricare nuovi elementi dalla rete;

  • Potresti prendere in considerazione l'utilizzo di GCD che ti aiuterà a "proteggere" il tuo codice dai problemi di gestione del ciclo di esecuzione. Nell'esempio sopra, potresti considerare di aggiungere le tue richieste di rete a una coda seriale personalizzata.


9
Caro Viggio24, grazie mille per questa spiegazione pulita e precisa. Chiederei ad Apple di includere il tuo commento nella loro guida API. ;)
Stkim1

7
La risposta di viggio24 è perfetta. Per chi fosse interessato, vorrei sottolineare che la sessione 208 (app di rete per iPhone OS, parte 2) da WWDC 2010 contiene un'introduzione sui cicli di esecuzione. Se sei interessato dai un'occhiata. Spero che sia d'aiuto.
Lorenzo B

19
Solo una nota per me: NSRunLoopCommonModesconsente l'evento timer durante lo scorrimento UIScrollView. NSDefaultRunLoopModeimpedire il timer durante lo scorrimento.
eonil

2
Ho trovato molto interessante il commento sull'aggiornamento della visualizzazione a scorrimento, poiché menziona un argomento molto impegnativo. Solo per aggiungere ulteriori dettagli su questo: quando si imposta una modalità per una connessione NSURLC, ciò influisce solo sull'esecuzione dei call-back delegati. Capisco che l'aggiornamento di scrollView qui potrebbe causare problemi di prestazioni, ma perché sta accadendo? Se la risposta è che l'immagine deve essere caricata in memoria, puoi farlo scrivendo in un contesto grafico sullo sfondo e aggiornare il livello del thread principale della vista dopo averlo fatto. questo suona ragionevole?
nebillo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.