@selector () no Swift? DoCow
nstimer rápido seletor
@selector () no Swift?
Estou tentando criar um NSTimer no Swift mas estou tendo alguns problemas.
test() é uma function da mesma class.
Criando um seletor a partir de um nome de método com parâmetros
Objective-C: Chamando seletores com vários argumentos
SEL performSelector e argumentos
Eu recebo um erro no editor:
Não foi possível encontrar uma sobrecarga para o 'init' que aceita os argumentos fornecidos
Quando eu mudo o selector: test() para selector: nil o erro desaparece.
Mas nada funciona e não consigo encontrar uma solução nas referências.
Seletores de lista para object Objective-C
O Swift em si não usa seletores – vários padrões de projeto que fazem uso de seletores no Objective-C funcionam de maneira diferente no Swift. (Por exemplo, use encadeamento opcional em tipos de protocolo ou is / as testes em vez de respondsToSelector: e use encerramentos sempre que possível, em vez de performSelector: para melhor segurança de tipo / memory.)
Mas ainda há várias APIs importantes baseadas em ObjC que usam seletores, incluindo timers e o padrão target / action. O Swift fornece o tipo Selector para trabalhar com eles. (Swift usa isso automaticamente no lugar do tipo SEL da ObjC.)
No Swift 2.2 (Xcode 7.3) e posterior (incluindo Swift 3 / Xcode 8 e Swift 4 / Xcode 9):
Você pode construir um Selector partir de um tipo de function Swift usando a expressão #selector .
O melhor desta abordagem? Uma referência de function é verificada pelo compilador Swift, portanto, você pode usar a expressão #selector somente com pares de classs / methods que realmente existem e são elegíveis para uso como seletores (consulte "Disponibilidade do seletor" abaixo). Você também é livre para tornar sua referência de function tão específica quanto você precisar, de acordo com as regras do Swift 2.2+ para nomeação de tipo de function .
(Isso é realmente uma melhoria em relação à diretiva @selector() do @selector() , porque a verificação do -Wundeclared-selector do compilador verifica apenas se o seletor nomeado existe. A referência da function Swift que você passa para #selector verifica a existência, a associação em uma class e a assinatura do tipo .)
Há algumas ressalvas extras para as referências de function que você passa para a expressão #selector :
Múltiplas funções com o mesmo nome base podem ser diferenciadas por seus labels de parâmetro usando a syntax mencionada anteriormente para referências de function (por exemplo, insertSubview(_:at:) vs insertSubview(_:aboveSubview:) ). Mas se uma function não tiver parâmetros, a única maneira de desambiguá-la é usar uma conversão com a assinatura do tipo da function (por exemplo, foo as () -> () vs foo(_:) ).
Há uma syntax especial para pares de getter / setter de propriedade no Swift 3.0+. Por exemplo, dado um var foo: Int , você pode usar #selector(getter: MyClass.foo) ou #selector(setter: MyClass.foo) .
Casos em que #selector não funciona e nomeação: Às vezes você não tem uma referência de function para fazer um seletor com (por exemplo, com methods registrados dinamicamente no runtime ObjC). Nesse caso, você pode construir um Selector partir de uma string: por exemplo, Selector("dynamicMethod:") – embora você perca a verificação de validade do compilador. Quando você faz isso, você precisa seguir as regras de nomenclatura ObjC, incluindo dois pontos (:) para cada parâmetro.
Disponibilidade do seletor: o método referenciado pelo seletor deve ser exposto ao tempo de execução ObjC. No Swift 4, todo método exposto a ObjC deve ter sua declaração precedida pelo atributo @objc . (Nas versões anteriores, você tem esse atributo de graça em alguns casos, mas agora você precisa declará-lo explicitamente.)
Lembre-se de que private símbolos private também não estão expostos ao tempo de execução – seu método precisa ter, pelo menos, visibilidade internal .
Caminhos principais: estão relacionados, mas não exatamente, aos seletores. Há uma syntax especial para estes no Swift 3, por exemplo: chris.valueForKeyPath(#keyPath(Person.friends.firstName)) . Veja SE-0062 para detalhes. E ainda mais coisas do KeyPath no Swift 4 , certifique-se de usar a API correta baseada no KeyPath em vez de seletores, se apropriado.
Você pode ler mais sobre seletores em Interagindo com APIs Objective-C em Usando Swift com Cocoa e Objective-C .
Nota: Antes do Swift 2.2, o Selector estava em conformidade com o StringLiteralConvertible , portanto, você pode encontrar um código antigo no qual as strings nuas são passadas para APIs que usam seletores. Você vai querer executar o "Convert to Current Swift Syntax" no Xcode para obter aqueles usando o #selector .
Veja um exemplo rápido de como usar a class Selector no Swift:
Observe que, se o método transmitido como uma string não funcionar, ele falhará no tempo de execução, não no tempo de compilation e interromperá seu aplicativo. Seja cuidadoso
Além disso, se a sua class (Swift) não descer de uma class Objective-C, então você deve ter dois pontos no final da string de nome do método de destino e você deve usar a propriedade @objc com seu método de destino, por exemplo
caso contrário, você receberá um erro "Seletor não reconhecido" no tempo de execução.
Para os futuros leitores, descobri que tive um problema e estava recebendo um unrecognised selector sent to instance erro de unrecognised selector sent to instance causado pela marcação da func target como private.
O func deve ser publicamente visível para ser chamado por um object com uma referência a um seletor.
Atualização Swift 2.2+ e Swift 3
Use a nova expressão #selector , que elimina a necessidade de usar literais de string, tornando o uso menos propenso a erros. Para referência:
Veja também: Proposta Swift Evolution
Se usando #selector você precisaria marcar a function como @objc
Apenas no caso de alguém ter o mesmo problema que tive com o NSTimer, onde nenhuma das outras respostas resolveu o problema, é realmente importante mencionar que, se você estiver usando uma class que não herde do NSObject diretamente ou no fundo da hierarquia ( Por exemplo, arquivos swift criados manualmente), nenhuma das outras respostas funcionará mesmo quando especificado da seguinte maneira:
Sem alterar nada além de fazer a class herdar do NSObject, parei de receber o erro "Unrecognized selector" e obtive minha lógica funcionando como esperado.
você cria o Seletor como abaixo.
1. Adicione o evento a um botão como:
e a function será como abaixo:
Se você quiser passar um parâmetro para a function do NSTimer, então aqui está sua solução:
Inclua os dois pontos no texto do seletor (testador 🙂 e seu (s) parâmetro (s) vão em userInfo.
Sua function deve usar o NSTimer como parâmetro. Em seguida, basta extrair userInfo para obter o parâmetro passado.
Seletores são uma representação interna de um nome de método em Objective-C. Em Objective-C "@selector (methodName)" iria converter um método de código fonte em um tipo de dados de SEL. Como você não pode usar a syntax @selector no Swift (o rickster está lá), você precisa especificar manualmente o nome do método como um object String diretamente, ou passando um object String para o tipo Seletor. Aqui está um exemplo:
var rightBarButton = UIBarButtonItem( title: "Logout", style: UIBarButtonItemStyle.Plain, target: self, action:"logout" )
Com amostra de gesto de toque
Veja o documento da Apple para mais detalhes sobre: Expressão do Seletor
// Refresh Control Method
Desde que o Swift 3.0 é publicado, é até um pouco mais sutil declarar um alvo.
Ao usar performSelector()
/addtarget()/NStimer.scheduledTimerWithInterval() methods seu método (correspondente ao seletor) deve ser marcado como
Para o Swift 2.2, você precisa escrever '#selector ()' em vez de string e nome do seletor para que as possibilidades de erro de ortografia e travamento devido a isso não estejam mais lá. Abaixo está o exemplo
Observe que a syntax @selector desapareceu e foi substituída por uma String simples nomeando o método para chamar. Há uma área onde todos podemos concordar que a verbosidade ficou no caminho. Claro, se declaramos que existe um método de destino chamado flatButtonPressed: é melhor escrevermos um:
definir o timer:
Para ser completo, aqui está o flatButtonPressed
Eu achei muitas dessas respostas úteis, mas não estava claro como fazer isso com algo que não era um botão. Eu estava adicionando um reconhecedor de gestos a um UILabel rapidamente e me esforcei, então aqui está o que eu achei que funcionou para mim depois de ler tudo acima:
Onde o "Seletor" foi declarado como:
Observe que é público e que não estou usando a syntax Selector (), mas é possível fazer isso também.
Usando #selector irá verificar o seu código em tempo de compilation para se certificar de que o método que você deseja chamar realmente existe. Melhor ainda, se o método não existir, você receberá um erro de compilation: o Xcode se recusará a criar seu aplicativo, banindo assim o esquecimento de outra possível fonte de bugs.
Pode ser útil observar onde você configura o controle que aciona a ação.
Por exemplo, descobri que ao configurar um UIBarButtonItem, eu tinha que criar o botão dentro de viewDidLoad ou então eu iria obter uma exceção de seletor não reconhecido.
Altere como uma simples nomeação de string no método que chama a syntax do seletor
Depois disso, digite func test ().
Para 3 rápido
Declaração de Função na Mesma Classe
// Código de amostra para criar timer
Obter parâmetros de consulta individuais de Uri É possível fazer uma Tree View com Angular? jQuery ajax load () script java não está executando? Por que os construtores não são herdados? Obtendo o endereço IP do cliente O CSS tem um seletor de borrões (pseudo-class)? Obter uma lista de resources do diretório classpath Conceitos básicos do MVVM – o que um ViewModel deve fazer? Por que o intervalo de bytes -128 a 127 em Java? Alinhar texto na linha inclinada Posso fazer solicitações POST ou GET de um aplicativo do iphone? nodejs como ler as teclas digitadas de stdin É apropriado estender o Controle para fornecer uma funcionalidade Invoke / BeginInvoke consistente e segura? O que é o escopo léxico? Consuma o serviço da Web WCF usando o Objective-C no iPhone