É possível em Swift? Caso contrário, existe uma solução alternativa para fazer isso?
ios
swift
swift-protocols
swift-extensions
Selvin
fonte
fonte
Respostas:
1. Utilizando implementações padrão (preferencial).
Vantagens
Nenhum tempo de execução do Objective-C está envolvido (bem, pelo menos não explicitamente). Isso significa que você pode conformar estruturas, enumerações e não
NSObject
classes a ele. Além disso, isso significa que você pode tirar proveito do poderoso sistema de genéricos.Você sempre pode ter certeza de que todos os requisitos sejam atendidos ao encontrar tipos que estejam em conformidade com esse protocolo. É sempre uma implementação concreta ou padrão. É assim que "interfaces" ou "contratos" se comportam em outros idiomas.
Desvantagens
Para não-
Void
requisitos, você precisa ter um valor padrão razoável , o que nem sempre é possível. No entanto, quando você encontra esse problema, significa que esse requisito realmente não deve ter uma implementação padrão ou que você cometeu um erro durante o design da API.Você não pode distinguir entre uma implementação padrão e nenhuma implementação , pelo menos sem resolver esse problema com valores de retorno especiais. Considere o seguinte exemplo:
Se você fornecer uma implementação padrão que apenas retorna
true
- tudo bem à primeira vista. Agora, considere o seguinte pseudo-código:Não há como implementar essa otimização - você não pode saber se seu delegado implementa um método ou não.
Embora haja várias maneiras diferentes de superar esse problema (usando fechamentos opcionais, objetos delegados diferentes para operações diferentes, entre outros), esse exemplo apresenta o problema claramente.
2. Usando
@objc optional
.Vantagens
Desvantagens
Isso limita severamente os recursos do seu protocolo, exigindo que todos os tipos em conformidade sejam compatíveis com Objective-C. Isso significa que apenas as classes herdadas
NSObject
podem estar em conformidade com esse protocolo. Sem estruturas, sem enumerações, sem tipos associados.Você sempre deve verificar se um método opcional é implementado , opcionalmente, chamando ou verificando se o tipo conforme o implementa. Isso pode introduzir muitos clichês se você estiver chamando métodos opcionais com frequência.
fonte
respondsToSelector
?optional func doSomething(param: Int?)
No Swift 2 e em diante, é possível adicionar implementações padrão de um protocolo. Isso cria uma nova maneira de métodos opcionais em protocolos.
Não é uma maneira muito boa de criar métodos opcionais de protocolo, mas oferece a possibilidade de usar estruturas em retornos de chamada de protocolo.
Eu escrevi um pequeno resumo aqui: https://www.avanderlee.com/swift-2-0/optional-protocol-methods/
fonte
Como existem algumas respostas sobre como usar o modificador opcional e o atributo @objc para definir o protocolo de requisitos opcional, darei uma amostra sobre como usar extensões de protocolo para definir o protocolo opcional.
O código abaixo é o Swift 3. *.
Observe que os métodos de extensão de protocolo não podem ser invocados pelo código Objective-C e, pior ainda, a equipe Swift não o corrigirá. https://bugs.swift.org/browse/SR-492
fonte
As outras respostas aqui envolvendo a marcação do protocolo como "@objc" não funcionam ao usar tipos específicos rápidos.
Para declarar protocolos opcionais que funcionam bem com o swift, declare as funções como variáveis em vez de func.
E, em seguida, implemente o protocolo da seguinte maneira
Você pode usar "?" para verificar se a função foi ou não implementada
fonte
Aqui está um exemplo concreto com o padrão de delegação.
Configure seu protocolo:
Defina o delegado para uma classe e implemente o protocolo. Veja que o método opcional não precisa ser implementado.
Uma coisa importante é que o método opcional é opcional e precisa de um "?" ao ligar. Mencione o segundo ponto de interrogação.
fonte
No Swift 3.0
Isso economizará seu tempo.
fonte
@objc
é necessária em todos os membros agora?required
flag, mas com erros:required
só pode ser usado em declarações 'init'.optional
palavra-chave antes de cada método.fonte
@objc
, não apenas o protocolo.Uma abordagem Swift pura com herança de protocolo:
fonte
Para ilustrar a mecânica da resposta de Antoine:
fonte
Penso que antes de perguntar como você pode implementar um método de protocolo opcional, você deve estar se perguntando por que deveria implementar um.
Se pensarmos em protocolos rápidos como uma interface na programação clássica orientada a objetos, métodos opcionais não fazem muito sentido, e talvez uma solução melhor seria criar implementação padrão ou separar o protocolo em um conjunto de protocolos (talvez com algumas relações de herança entre eles) para representar a possível combinação de métodos no protocolo.
Para uma leitura mais detalhada, consulte https://useyourloaf.com/blog/swift-optional-protocol-methods/ , que fornece uma excelente visão geral sobre esse assunto.
fonte
Um pouco fora do tópico da pergunta original, mas parte da ideia de Antoine e achei que poderia ajudar alguém.
Você também pode tornar as propriedades computadas opcionais para estruturas com extensões de protocolo.
Você pode tornar uma propriedade no protocolo opcional
Implemente a propriedade computada fictícia na extensão de protocolo
E agora você pode usar estruturas que possuem ou não a propriedade opcional implementada
Também escrevi como fazer propriedades opcionais nos protocolos Swift no meu blog , que vou manter atualizado caso as coisas mudem com os lançamentos do Swift 2.
fonte
Como criar métodos delegados opcionais e necessários.
fonte
Aqui está um exemplo muito simples para Classes rápidas, e não para estruturas ou enumerações. Observe que o método do protocolo, sendo opcional, possui dois níveis de encadeamento opcional em ação. Além disso, a classe que adota o protocolo precisa do atributo @objc em sua declaração.
fonte
delegate?.indexDidChange?(index!)
:?protocol CollectionOfDataDelegate{ func indexDidChange(index: Int) }
então você o chamaria sem o ponto de interrogação:delegate?.indexDidChange(index!)
Quando você define um requisito opcional para um método em um protocolo, o Tipo que se conforma a ele NÃO pode implementar esse método , então?
é usado para verificar a implementação e, se não houver, o programa não falhará. @Unheiligweak var delegate : CollectionOfDataDelegate?
(assegurar referência fraca?)delegate?
uso à sua resposta? Essa informação deve realmente pertencer a outras pessoas no futuro. Eu quero aprovar isso, mas essa informação deve realmente estar na resposta.se você quiser fazê-lo em puro swift, a melhor maneira é fornecer uma partição padrão de implementação se você retornar um tipo Swift, como por exemplo struct com tipos Swift
exemplo:
então você pode implementar o protocolo sem definir todas as funções
fonte
Existem duas maneiras de criar um método opcional no protocolo rápido.
1 - A primeira opção é marcar o seu protocolo usando o atributo @objc. Enquanto isso significa que ele pode ser adotado apenas por classes, significa que você marca métodos individuais como opcionais como este:
2 - Uma maneira mais rápida: Esta opção é melhor. Escreva implementações padrão dos métodos opcionais que não fazem nada, como este.
O Swift possui um recurso chamado extension que nos permite fornecer uma implementação padrão para os métodos que queremos que sejam opcionais.
fonte
Uma opção é armazená-los como variáveis de função opcionais:
fonte
Defina a função no protocolo e crie extensão para esse protocolo e crie uma implementação vazia para a função que você deseja usar como opcional.
fonte
Para definir
Optional
Protocol
rapidamente, você deve usar a@objc
palavra-chave antes daProtocol
declaração eattribute
/method
declaração dentro desse protocolo. Abaixo está uma amostra da propriedade opcional de um protocolo.fonte
Coloque
@optional
na frente de métodos ou propriedades.fonte
@optional
nem sequer é a palavra-chave correta. Éoptional
, e você deve declarar a classe e o protocolo com o@objc
atributo