Ainda sou meio novo em Objective-C e me pergunto qual é a diferença entre as duas declarações a seguir.
[object performSelector:@selector(doSomething)];
[object doSomething];
objective-c
selector
dynamic-languages
method-dispatch
TheGambler
fonte
fonte
performSelector:
é algo que você provavelmente só fará se implementar ação-alvo em sua classe. Os irmãosperformSelectorInBackground:withObject:
eperformSelectorOnMainThread:withObject:waitUntilDone:
muitas vezes são mais úteis. Para gerar um thread de segundo plano e para chamar de volta os resultados do thread de segundo plano para o thread principal.performSelector
também é útil para suprimir avisos de compilação. Se você souber que o método existe (como após o usorespondsToSelector
), ele impedirá o Xcode de dizer "pode não responder ayour_selector
". Apenas não o use em vez de descobrir a verdadeira causa do aviso. ;)Para este exemplo básico na questão,
não há diferença no que vai acontecer. doSomething será executado de forma síncrona pelo objeto. Apenas "doSomething" é um método muito simples, que não retorna nada e não requer nenhum parâmetro.
fosse algo um pouco mais complicado, como:
as coisas ficariam complicadas, porque [object doSomethingWithMyAge: 42];
não pode mais ser chamado com qualquer variante de "performSelector", porque todas as variantes com parâmetros aceitam apenas parâmetros de objeto.
O seletor aqui seria "doSomethingWithMyAge:" mas qualquer tentativa de
simplesmente não compila. passar um NSNumber: @ (42) em vez de 42 também não ajudaria, porque o método espera um tipo C básico - não um objeto.
Além disso, existem variantes performSelector de até 2 parâmetros, não mais. Embora os métodos muitas vezes tenham muitos mais parâmetros.
Eu descobri que, embora sejam variantes síncronas de performSelector:
sempre retornava um objeto, consegui retornar um simples BOOL ou NSUInteger também, e funcionou.
Um dos dois principais usos de performSelector é compor dinamicamente o nome do método que você deseja executar, conforme explicado em uma resposta anterior. Por exemplo
O outro uso é enviar assincronamente uma mensagem para o objeto, que será executado posteriormente no runloop atual. Para isso, existem várias outras variantes do performSelector.
(sim, reuni-os de várias categorias de classe Foundation, como NSThread, NSRunLoop e NSObject)
Cada uma das variantes tem seu próprio comportamento especial, mas todas compartilham algo em comum (pelo menos quando waitUntilDone está definido como NO). A chamada "performSelector" retornaria imediatamente e a mensagem para o objeto só seria colocada no runloop atual após algum tempo.
Por causa da execução atrasada - naturalmente, nenhum valor de retorno está disponível do método do seletor, portanto, o valor de retorno - (vazio) em todas essas variantes assíncronas.
Espero ter coberto isso de alguma forma ...
fonte
@ennuikiller está certo. Basicamente, os seletores gerados dinamicamente são úteis quando você não sabe (e geralmente não pode) saber o nome do método que estará chamando ao compilar o código.
Uma diferença importante é que
-performSelector:
e amigos (incluindo as variantes multi-threaded e atrasadas ) são um tanto limitados, pois são projetados para uso com métodos com parâmetros 0-2. Por exemplo, chamar-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:
com 6 parâmetros e retornar oNSString
é muito complicado e não é compatível com os métodos fornecidos.fonte
NSInvocation
objeto.performSelector:
e todos os amigos aceitam argumentos de objeto, o que significa que você não pode usá-los para chamar (por exemplo)setAlphaValue:
, porque seu argumento é um float.Os seletores são um pouco como os ponteiros de função em outras linguagens. Você os usa quando não sabe em tempo de compilação qual método deseja chamar em tempo de execução. Além disso, como os ponteiros de função, eles encapsulam apenas a parte do verbo da invocação. Se o método tiver parâmetros, você também precisará passá-los.
Um
NSInvocation
serve a um propósito semelhante, exceto pelo fato de reunir mais informações. Não inclui apenas a parte do verbo, também inclui o objeto de destino e os parâmetros. Isso é útil quando você deseja chamar um método em um objeto específico com parâmetros específicos, não agora, mas no futuro. Você pode construir um apropriadoNSInvocation
e dispará-lo mais tarde.fonte
Existe outra diferença sutil entre os dois.
Aqui está o trecho da documentação da Apple
"performSelector: withObject: afterDelay: Executa o seletor especificado no encadeamento atual durante o próximo ciclo de loop de execução e após um período de atraso opcional. Como ele espera até o próximo ciclo de loop de execução para realizar o seletor, esses métodos fornecem um mini atraso automático de o código em execução no momento. Vários seletores na fila são executados um após o outro na ordem em que foram colocados na fila. "
fonte
performSelector:withObject:afterDelay:
, mas a pergunta e seu trecho estão usandoperformSelector:
, que é um método totalmente diferente. Dos documentos para ele: <quote> OperformSelector:
método é equivalente a enviar umaaSelector
mensagem diretamente para o destinatário. </quote>performSelector/performSelector:withObject/performSelector:withObject:afterDelay
todos se comportavam da mesma maneira, o que foi um erro.