Por que o Swift 3 @objc inference está ficando no passado?
\n\nSe você já atualizou um projeto de Swift 3 para Swift 4, certamente se deparou com o assustador aviso do compilador:
\n\nThe use of Swift 3 @objc inference in Swift 4 mode is deprecated. \nPlease address this deprecated @objc inference warning, \nor disable the warning by setting the "Swift 3 @objc Inference" \nbuild setting to "Default" for the "Swift 4" target.\n\nEsta mensagem não é apenas uma formalidade. Por trás dela, há uma importante mudança na filosofia da linguagem. No Swift 3, o compilador decidia por si só quais métodos e propriedades deveriam ser visíveis para o Objective-C. Isso era conveniente, mas criava problemas ocultos: o tamanho do binário aumentava e o desempenho caía. O Swift 4 decidiu acabar com essa "adivinhação" e transferiu o controle para o desenvolvedor.
\n\nNeste artigo, vamos analisar o que é @objc inference, por que foi depreciado, como corrigir o aviso e quais as melhores práticas a serem usadas em projetos modernos. Vamos lá!
\n\nO que é @objc inference e como funcionava no Swift 3?
\n\nNo Swift 3, existia uma conversão implícita para @objc. Isso significava que, se uma classe herdasse de NSObject ou usasse um protocolo @objc, o compilador tornava automaticamente todos os seus métodos visíveis para o Objective-C. O mecanismo era chamado de @objc inference (inferência implícita).
\n\nExemplo no Swift 3:
\n\nclass MyViewController: UIViewController {\n func buttonTapped() {\n print("Button tapped")\n }\n}\n\nNo Swift 3, o método buttonTapped() tornava-se automaticamente @objc. Você poderia passá-lo para #selector ou usá-lo como target para UIControl. Conveniente? Sim. Mas o preço era o inchaço injustificado do binário e a perda de otimizações.
Por que a Apple decidiu abandonar a inferência automática?
\n\nExistem várias razões, e todas elas são sobre eficiência e controle:
\n\n- \n
- Tamanho do aplicativo. Cada método marcado como @objc gera um wrapper adicional para o runtime do Objective-C. Em projetos grandes, isso podia adicionar megabytes de código desnecessário. \n
- Desempenho. Swift é uma linguagem com tipagem estática e otimização poderosa. Assim que um método se torna @objc, o compilador perde a capacidade de aplicar uma série de otimizações (por exemplo, inlining). \n
- Explicitude. O Swift 4 adotou um rumo em direção à explicitude. O desenvolvedor deve decidir por si mesmo o que deve estar acessível a partir do Objective-C. Isso simplifica a compreensão do código e reduz erros inesperados. \n
- Futuro do Swift. A Apple está gradualmente se afastando da dependência do Objective-C. Quanto menos pontes implícitas, mais rápido o Swift poderá se tornar uma linguagem totalmente independente. \n
Como é o aviso na prática?
\n\nSuponha que você tenha um projeto escrito em Swift 3. Você altera a configuração "Swift Language Version" para Swift 4.0 e obtém dezenas (ou até centenas) desses avisos:
\n\nclass LegacyViewController: UIViewController {\n // Aviso: The use of Swift 3 @objc inference in Swift 4 mode is deprecated\n func legacyAction() {\n // ...\n }\n\n @objc func explicitAction() {\n // Este método já está marcado com @objc — tudo certo\n }\n}\n\nO compilador reclama de legacyAction(), pois ele não está marcado com @objc, mas antes o compilador fazia isso automaticamente. Agora, é preciso uma solução.
Três maneiras de corrigir o aviso
\n\nVocê tem três opções de ação. Escolha a que melhor se