O uso da inferência Swift 3 @objc no modo Swift 4 está obsoleto?

485

Resumidamente, ao usar o Xcode 9 Beta, encontrei o seguinte aviso:

O uso da inferência Swift 3 @objc no modo Swift 4 está obsoleto. Dirija-se aos avisos obsoletos da inferência @objc, teste seu código com o log "Uso da inferência Swift 3 @objc" obsoleta ativado e desabilite a inferência do Swift 3 @objc. **

Após algumas pesquisas, ainda não tenho idéia de como corrigir o problema. Eu gostaria muito de receber dicas sobre como corrigir esse problema, bem como uma explicação do que está acontecendo.

Meu objetivo é entender melhor o que está acontecendo com meu código.

DaleK
fonte
4
Eu realmente não recebo da mensagem de aviso qual objeto está causando isso. O Xcode simplesmente não diz em qual linha esse objeto está. Alguma dica de como descobrir de onde vem esse aviso?
olyv

Respostas:

816

Eu me livrei desse aviso alterando a configuração de compilação "Swift 3 @objc Inference" dos meus destinos para "Padrão".

Desativar a inferência Swift 3 @objc no Xcode9

Deste artigo :

Antes do Swift 4, o compilador disponibilizava algumas declarações do Swift automaticamente para o Objective-C . Por exemplo, se uma subclasse de NSObject, o compilador criou pontos de entrada Objective-C para todos os métodos em tais classes. O mecanismo é chamado de inferência @objc.

No Swift 4, essa inferência automática do @objc é preterida porque é caro gerar todos esses pontos de entrada do Objective-C. Quando a configuração "Swift 3 @objc Inference" está definida como "On", permite que o código antigo funcione. No entanto, ele mostrará avisos de descontinuação que precisam ser resolvidos. É recomendável "corrigir" esses avisos e alterar a configuração para "Padrão" , que é o padrão para novos projetos Swift.

Consulte também esta proposta Swift para obter mais informações.

Evgenii
fonte
5
Obrigado Evgenii. Esta é uma solução a longo prazo?
Dalek
6
@DaleK sim, acredito que sim. De acordo com a proposta Swift que mencionei na minha resposta, a inferência objc é obsoleta. A configuração "Swift 3 objc Inference" está presente apenas nos projetos que foram migrados de versões mais antigas do Swift. Se alguém criar um novo projeto, a configuração não estará mais presente, o que significa que a inferência objetiva está desativada. Recomenda-se endereçar qualquer aviso de inferência de objeção e defini-lo como "Desligado".
Evgenii
4
A mensagem informativa no XCode sugere que: "O uso da @objcinferência Swift 3 no modo Swift 4 está obsoleto. Envie os @objcavisos de inferência obsoletos , teste seu código com o @objclog " Uso da inferência Swift 3 obsoleta "ativado e desative a @objcinferência Swift 3 ". Alguma idéia de onde ativar o referido @objcregistro de inferência Swift 3 ?
precisa
4
@courteouselk, de acordo com a proposta Swift, é possível definir a variável de ambiente SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT como valores de 1 a 3 para ver o uso dos pontos de entrada do Objective-C nos logs.
precisa
14
Apenas para adicionar - Você precisa fazer isso para todos os tagets de construção, não apenas para o projeto.
Krivvenz 4/17/17
270

- O que é @objcinferência? O que está acontecendo?

Em Swift 3, o compilador deduz @objcem vários lugares para que você não precise. Em outras palavras, certifica-se de adicionar @objcpara você!

Em Swift 4, o compilador não faz mais isso (tanto). Agora você deve adicionar @objcexplicitamente.

Por padrão, se você tiver um projeto anterior ao Swift 4, receberá avisos sobre isso. Em um projeto Swift 4, você receberá erros de construção. Isso é controlado através da SWIFT_SWIFT3_OBJC_INFERENCEconfiguração de compilação. Em um projeto pré-Swift 4, isso é definido como On. Eu recomendaria definir isso como Default(ou Off), que agora é a opção padrão em um novo projeto.

Levará algum tempo para converter tudo, mas como é o padrão para o Swift 4, vale a pena fazê-lo.

- Como interrompo os avisos / erros do compilador?

Existem duas maneiras de converter seu código para que o compilador não se queixe.

Uma é usar @objcem cada função ou variável que precisa ser exposta ao tempo de execução do Objective-C:

@objc func foo() {

}

O outro é usar @objcMemberspor uma Classdeclaração. Isso garante adicionar automaticamente @objca TODAS as funções e variáveis ​​da classe. Essa é a maneira mais fácil, mas tem um custo, por exemplo, pode aumentar o tamanho do seu aplicativo, expondo funções que não precisavam ser expostas.

@objcMembers class Test {

}

- O que é @objce por que é necessário?

Se você introduzir novos métodos ou variáveis ​​em uma classe Swift, marcando-os como os @objcexpõe ao tempo de execução Objective-C. Isso é necessário quando você possui um código Objective-C que usa sua classe Swift ou, se você estiver usando recursos do tipo Objective-C, como Selectors. Por exemplo, o padrão de ação de destino: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Por que eu não marcaria tudo @objc?

Existem negativos que vêm marcando algo como @objc:

  • Aumento do tamanho binário do aplicativo
  • Sem sobrecarga de função

Lembre-se de que este é um resumo de alto nível e mais complicado do que escrevi. Eu recomendaria ler a proposta real para obter mais informações.

Fontes:

kgaidis
fonte
@objcnão implica expedição dinâmica, o Swift é livre para usar expedição estática ou virtual (e, possivelmente, executar código diferente como resultado). A dynamicpalavra-chave é necessária para forçar o Swift a usar o envio dinâmico.
kevin
7
Existem outras maneiras de adicionar ação ao botão? Se @objcprivar o que devemos usar?
Aznix 21/09/17
5
@ Stefan sim, pode haver um pouco para converter. Divida-o em etapas. Deixe SWIFT_SWIFT3_OBJC_INFERENCEàs On. Converta para o Swift 4. Em seguida, lide com as @objccoisas. Para simplificar, siga as regras básicas: SE a classe Swift for usada no código Objc-C (via cabeçalho de ponte), use @objcMembers, caso contrário, uma adição um a um @objc. Basta usar a pesquisa do Xcode para descobrir se a classe Swift é chamada a partir de qualquer .marquivo. Isso deve tornar a conversão relativamente indolor.
precisa saber é o seguinte
5
@DaleK, essa resposta deve ser aceita. Suprimir avisos e fazer as coisas funcionarem como no Swift 3 é uma opção, mas IMHO não é a melhor. É importante entender por que o @objcSwift 4 mudou e, em seguida, tomar a decisão de corrigir o projeto e mantê-lo da mesma forma.
Derpoliuk 17/11/19
2
Obrigado por este breve explicação
Schmoudi
48

Migrator não consegue identificar todas as funções que necessidade @objc Inferido Objective-C thunks marcados como obsoleto para ajudar a encontrar-los
• Construir avisos sobre métodos obsoletos
• Mensagens de Console ao executar obsoleto thunks

insira a descrição da imagem aqui

Hassan Taleb
fonte
1
Então, o que devo fazer com o @objc? remova? deixar? Eu já removi isso. e eu recebi esses avisos, então eu tenho que adicioná-los? que na etapa 3 devo fazer isso?
Shial 20/09/17
Adicionar @objc pouco antes func
Hassan Taleb
1
Qual é o passo 3? Você pode adicionar algumas descrições :)
Shial
E, no meu caso, recebo esse aviso, mas nenhum código é apontado. Existem dois métodos marcados com @objc e eles parecem os únicos que precisam dele. Eu mudei para Padrão e ainda recebo os avisos durante a compilação.
Maury Markowitz
12

Eu recebi esse aviso com a configuração "Swift 3 @objc Inference" = "Padrão". Então percebi que estava definido para o projeto - não para o alvo. Portanto, verifique se você tem a configuração "Padrão" em seu destino para se livrar do aviso.

Dmitry
fonte
Perdi 20 minutos procurando resolver o erro mesmo depois de alterar para Padrão nas configurações do projeto. Você apontou exatamente o que também precisa ser alterado no destino.
SkrewEverything
8

Você pode simplesmente passar para "padrão" em vez de "ON". Parece mais aderente à lógica da Apple.

(mas todos os outros comentários sobre o uso de @objpermanecem válidos.)

ingconti
fonte
7

Na verdade, você se livrará desses avisos desativando o Swift 3 @objc Inference. No entanto, problemas sutis podem aparecer. Por exemplo, o KVO irá parar de funcionar. Esse código funcionou perfeitamente no Swift 3:

for (key, value) in jsonDict {
    if self.value(forKey: key) != nil {
        self.setValue(value, forKey: key)
    }
}

Depois de migrar para o Swift 4 e definir "Swift 3 @objc Inference" como padrão, certos recursos do meu projeto pararam de funcionar . Levei algumas depurações e pesquisas para encontrar uma solução para isso. De acordo com o meu melhor conhecimento, aqui estão as opções:

  • Ative "Swift 3 @objc Inference" (funciona apenas se você tiver migrado um projeto existente do Swift 3) insira a descrição da imagem aqui
  • Marque os métodos e propriedades afetados como @objc insira a descrição da imagem aqui
  • Reative a inferência ObjC para toda a classe usando @objcMembers insira a descrição da imagem aqui

A reativação da inferência @objc deixa você com os avisos, mas é a solução mais rápida. Observe que ele está disponível apenas para projetos migrados de uma versão anterior do Swift. As outras duas opções são mais tediosas e requerem alguns testes de digitação de código e extensos.

Consulte também https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md

Karoly Nyisztor
fonte
7

Sou um desenvolvedor ocasional do iOS (em breve será mais), mas ainda não consegui encontrar a configuração conforme guiada pela outra resposta (já que eu não tinha esse item de chaveiro, a resposta mostra), então agora que o encontrei, pensei Posso apenas adicionar este instantâneo com os locais destacados nos quais você precisará clicar e encontrar.

  1. Comece no canto superior esquerdo
  2. Escolha o ícone da pasta do projeto
  3. Escolha o nome do projeto principal abaixo do ícone da pasta do projeto.
  4. Escolha Configurações de compilação no lado direito.
  5. Escolha seu projeto em TARGETS.
  6. Role muito para baixo (ou pesquise a palavra inferência na caixa de texto de pesquisa)

Localizando a configuração

raddevus
fonte
6

Você pode tentar "Atualização do pod" e / ou "limpeza rápida"

Também defino essa configuração no xcode.

A configuração da interface Objective-C é a seguinte:

Configuração da interface ObjectiveC

wisekiddo
fonte
2

Inferência Swift 3 @objc O uso da inferência Swift 3 @objc no modo Swift 4 foi descontinuado. Dirija-se aos avisos obsoletos do @objc inference, teste seu código com o "Uso do Swift 3 @objc inference" obsoleto ativado e desative a inferência alterando a configuração de compilação "Swift 3 @objc Inference" para "Padrão" para o "XMLParsingURL" alvo.

chegou ao

  1. A primeira etapa obteve a configuração de compilação

  2. Pesquisar para criar inferência de configuração

  3. change swift 3 @objc Inferência Padrão

insira a descrição da imagem aqui

Praveen Kumar
fonte
1

Tudo o que você precisa é apenas executar uma espera de teste até o final. Depois disso, vá para Build Setting, pesquise em Build Setting Inference, altere swift 3 @objc Inference para (Padrão). foi tudo o que fiz e funcionou perfeitamente.

Acasey
fonte
0

O uso da inferência Swift 3 @objc no modo Swift 4 está obsoleto?

usar chamada de função @objc

func call(){

foo()

}

@objc func foo() {

}
Puji Wahono
fonte
0

Além do que @wisekiddo disse, você também pode modificar as configurações de compilação no project.pbxprojarquivo, definindo a Swift 3 @obj Inference como padrão, como SWIFT_SWIFT3_OBJC_INFERENCE = Default;para seus sabores de compilação (por exemplo, depuração e liberação), especialmente se você vier de outro ambiente além do Xcode

DaveNOTDavid
fonte