Implementar protocolo parcialmente em Objective C e parcialmente em Swift
Posso implementar um protocolo parcialmente em Objective C e parcialmente em Swift?
Eu tenho uma classe Objective C existente que é declarada assim no arquivo .h.
@interface SetupViewController : UIViewController <UITableViewDataSource> {
// etc.
}
O arquivo .m correspondente implementa o protocolo UITableViewDataSource. Agora, quero reescrever alguns desses métodos em uma extensão do Swift. Mas eu esperava não ter que reescrever todos eles em Swift agora. (Este é apenas um trecho de exemplo, a aula real é muito mais longa.)
@implementation SetupViewController
// I want to rewrite this method in Swift
/*
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
*/
// I don't want to rewrite this method in Swift yet
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// lots of code
}
Então, movi um dos métodos do arquivo Objective C para minha extensão, assim:
@objc extension SetupViewController {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// new, more involved code
}
}
mas isso não vai compilar. Recebo um erro ao dizer Method 'tableView(_:numberOfRowsInSection:)' with Objective-C selector 'tableView:numberOfRowsInSection:' conflicts with previous declaration with the same Objective-C selector. Mas não tenho mais o numberOfRowsInSectionmétodo no arquivo Objective-C, tirei-o.
Parece que simplesmente colocar UITableViewDataSource no arquivo .h faz a extensão Swift pensar que já existem métodos implementados para cumprir o protocolo.
Também tentei declarar a extensão como @objc extension SetupViewController: UITableViewDataSourcee removê-la do arquivo .h, mas falhou porque a extensão não implementa o protocolo por si só.
Respostas
Ao construir um projeto que combina código Swift + Objective-C, este é um breve resumo do que acontece:
- o cabeçalho de ponte é processado
- os arquivos Swift são compilados
- os arquivos Objective-C são compilados
O erro que você vê ocorre na etapa 2, neste ponto o compilador vê que a classe Objective-C está em conformidade UITableViewDataSource, portanto, ele assume que o código Objective-C implementa o tableView(_:numberOfRowsInSection:)método, portanto, ele vê um conflito, pois o código Swift também implementa método.
A fonte do problema é o fato de que você está tentando implementar alguns dos métodos de protocolo em Objective-C e alguns em Swift, e isso não é possível, você também precisa implementar todos os métodos não opcionais do protocolo em Swift ou Objective-C.
Se você realmente deseja seguir esse caminho, uma solução possível seria mover a conformidade do protocolo no lado do Swift e declarar todos os outros métodos no cabeçalho Objective-C como métodos públicos dessa classe. Mas isso pode causar outros problemas ao longo do caminho.