Alguém pode explicar o que é NSRunLoop
? então pelo que eu sei NSRunLoop
é algo conectado com NSThread
certo? Então, suponha que eu crie um Tópico como
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
então após este Thread terminar seu trabalho certo? porque usar RunLoops
ou onde usar? dos documentos da Apple, eu li algo, mas não está claro para mim, então, explique da forma mais simples possível
ios
objective-c
cocoa-touch
nsrunloop
taffarel
fonte
fonte
Respostas:
Um loop de execução é uma abstração que (entre outras coisas) fornece um mecanismo para lidar com as fontes de entrada do sistema (soquetes, portas, arquivos, teclado, mouse, temporizadores, etc).
Cada NSThread tem seu próprio loop de execução, que pode ser acessado por meio do método currentRunLoop.
Em geral, você não precisa acessar o loop de execução diretamente, embora haja alguns componentes (de rede) que podem permitir que você especifique qual loop de execução eles usarão para processamento de E / S.
Um loop de execução para um determinado encadeamento esperará até que uma ou mais de suas fontes de entrada tenham alguns dados ou eventos e, em seguida, disparará o (s) manipulador (es) de entrada apropriado (s) para processar cada fonte de entrada que está "pronta".
Depois de fazer isso, ele retornará ao seu loop, processando a entrada de várias fontes e "dormindo" se não houver trabalho a fazer.
Essa é uma descrição de nível bastante elevado (tentando evitar muitos detalhes).
EDITAR
Uma tentativa de abordar o comentário. Eu o quebrei em pedaços.
De fato. NSRunLoop não é seguro para thread e só deve ser acessado a partir do contexto do thread que está executando o loop.
Se você quiser monitorar uma porta, basta adicionar essa porta ao loop de execução e, em seguida, o loop de execução observará a atividade dessa porta.
Você também pode adicionar um cronômetro explicitamente com
O loop de execução processará todos os eventos prontos a cada iteração (de acordo com seu modo). Você precisará consultar a documentação para descobrir sobre os modos de execução, pois isso está um pouco além do escopo de uma resposta geral.
Na maioria dos aplicativos, o loop de execução principal será executado automaticamente. No entanto, você é responsável por iniciar o loop de execução e responder aos eventos de entrada dos threads que rodar.
Não tenho certeza do que você quer dizer aqui. Você não adiciona eventos ao loop de execução. Você adiciona fontes de entrada e fontes de cronômetro (do thread que possui o loop de execução). O loop de corrida então observa a atividade deles. Você pode, é claro, fornecer entrada de dados de outros encadeamentos e processos, mas a entrada será processada pelo loop de execução que está monitorando essas fontes no encadeamento que está executando o loop de execução.
De fato. Na verdade, um loop de execução "permanecerá" em um manipulador de eventos até que ele retorne. Você pode ver isso em qualquer aplicativo de forma simples. Instale um manipulador para qualquer ação IO (por exemplo, pressionar o botão) que entra em suspensão. Você bloqueará o loop de execução principal (e toda a IU) até que o método seja concluído.
O mesmo se aplica a qualquer loop de execução.
Eu sugiro que você leia a seguinte documentação sobre loops de execução:
https://developer.apple.com/documentation/foundation/nsrunloop
e como eles são usados nos threads:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
fonte
performSelector:onThread:withObject:waitUntilDone:
, passando umNSThread
objeto e seu seletor será agendado no runloop desse thread.Eles permitem que você espere até que o usuário toque e responda de acordo, espere até obter um completeHandler e aplique seus resultados, espere até obter um cronômetro e executar uma função. Se você não tem um runloop, então você não pode ouvir / aguardar os toques do usuário, você não pode esperar até que uma chamada de rede esteja acontecendo, você não pode ser acordado em x minutos a menos que use
DispatchSourceTimer
ouDispatchWorkItem
Também a partir deste comentário :
Especificamente sobre: "Threads de fundo não têm seus próprios runloops". O seguinte cronômetro falha ao disparar por um despacho assíncrono :
Eu acho que a razão do
sync
bloco também ser executado é:blocos de sincronização geralmente são executados apenas de dentro da fila de origem . Neste exemplo, a fila de origem é a fila principal, o que quer que seja seja a fila de destino.
Para testar que eu loguei
RunLoop.current
dentro de cada despacho.O envio de sincronização tinha o mesmo loop de execução da fila principal. Enquanto o RunLoop dentro do bloco assíncrono era uma instância diferente das outras. Você pode estar pensando como por que
RunLoop.current
retorna um valor diferente. Não é compartilhado valor !? Ótima pergunta! Leia mais:NOTA IMPORTANTE:
A propriedade da classe
current
NÃO é uma variável global.É contextual. É visível apenas dentro do escopo do thread, ou seja , armazenamento local do thread . Para mais informações, veja aqui .
Este é um problema conhecido com temporizadores. Você não tem o mesmo problema se usar
DispatchSourceTimer
fonte
RunLoops são como uma caixa onde as coisas simplesmente acontecem.
Basicamente, em um RunLoop, você vai processar alguns eventos e depois retorna. Ou retorne se não processar nenhum evento antes que o tempo limite seja atingido. Você pode dizer que é semelhante a NSURLConnections assíncronos, Processando dados em segundo plano sem interferir no seu loop atual e, ao mesmo tempo, você precisa de dados de forma síncrona. O que pode ser feito com a ajuda do RunLoop que torna o seu assíncrono
NSURLConnection
e fornece dados na hora da chamada. Você pode usar um RunLoop como este:Neste RunLoop, ele será executado até que você conclua alguns de seus outros trabalhos e defina YourBoolFlag como false .
Da mesma forma, você pode usá-los em threads.
Espero que isso ajude você.
fonte
Daqui
Daqui
fonte