Como chamo o código Objective-C da Swift?

974

No Swift, como se chama o código Objective-C?

A Apple mencionou que eles poderiam coexistir em um aplicativo, mas isso significa que seria possível reutilizar tecnicamente as classes antigas feitas no Objective-C enquanto criava novas classes no Swift?

David Mulder
fonte
13
Consulte o guia da Apple sobre o uso de Swift com cacau e Objective-C .
Rickster #
10
Interessante que essa pergunta receba tantos votos positivos e recompensas. Quando vi pela primeira vez, pensei: RTFM. Como foi dito, ele realmente não mostra pesquisas, pois atualmente existem apenas dois ou três recursos que documentam oficialmente o Swift, e um deles é totalmente dedicado a exatamente isso (e está vinculado ao primeiro comentário).
Arquivo analógico
6
@EvolGate: exatamente o que está faltando no Objective C que impede que ele seja uma linguagem independente de plataforma? O idioma e as bibliotecas padrão de idioma são de código aberto. Você pode usar o Objective C no Windows, OS X, Linux, BSD, Solaris e qualquer outra plataforma suportada pelo GCC ou pelo LLVM. Você pode portar facilmente o Objective C para qualquer plataforma com um compilador C decente, mesmo que ele não seja suportado pelo GCC nem pelo LLVM. Não vejo como poderia ser mais independente da plataforma do que isso.
Arquivo analógico
2
@ DavidMulder: A seção "O raciocínio" ainda é necessária?
Franck

Respostas:

1395

Usando Classes Objective-C no Swift

Se você tem uma classe existente que gostaria de usar, execute a Etapa 2 e pule para a Etapa 5 . (Em alguns casos, tive que adicionar um explícito #import <Foundation/Foundation.ha um arquivo Objective-C mais antigo.)

Etapa 1: adicionar implementação de Objective-C - .m

Adicione um .marquivo à sua turma e nomeie-o CustomObject.m.

Etapa 2: adicionar o cabeçalho de ponte

Ao adicionar seu .marquivo, você provavelmente receberá um aviso parecido com este:

Uma caixa de diálogo em estilo de folha do macOS do Xcode perguntando se você "deseja configurar um cabeçalho de ponte Objective-C"

Clique em Yes !

Se você não viu o prompt ou excluiu acidentalmente o cabeçalho da ponte, adicione um novo .harquivo ao seu projeto e nomeie-o <#YourProjectName#>-Bridging-Header.h.

Em algumas situações, principalmente ao trabalhar com estruturas de Objective-C, você não adiciona uma classe de Objective-C explicitamente e o Xcode não consegue encontrar o vinculador. Nesse caso, crie seu .harquivo com o nome mencionado acima e, em seguida, certifique-se de vincular o caminho nas configurações do projeto do seu destino da seguinte maneira:

Uma animação demonstrando o parágrafo acima

Nota:

É uma boa prática vincular seu projeto usando a $(SRCROOT)macro para que, se você mover seu projeto ou trabalhar com outras pessoas usando um repositório remoto, ele ainda funcione. $(SRCROOT)pode ser considerado o diretório que contém o arquivo .xcodeproj. Pode ser assim:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

Etapa 3: Adicionar cabeçalho Objective-C - .h

Adicione outro .harquivo e nomeie-o CustomObject.h.

Etapa 4: Crie sua classe Objective-C

No CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

No CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

Etapa 5: adicionar classe ao ponte de cabeçalho

Em YourProject-Bridging-Header.h:

#import "CustomObject.h"

Etapa 6: use seu objeto

Em SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

Não há necessidade de importar explicitamente; é para isso que serve o cabeçalho da ponte.

Usando Classes Swift no Objective-C

Etapa 1: Criar nova classe Swift

Adicione um .swiftarquivo ao seu projeto e nomeie-o MySwiftObject.swift.

Em MySwiftObject.swift:

import Foundation

@objc(MySwiftObject)
class MySwiftObject : NSObject {

    @objc
    var someProperty: AnyObject = "Some Initializer Val" as NSString

    init() {}

    @objc
    func someFunction(someArg: Any) -> NSString {
        return "You sent me \(someArg)"
    }
}

Etapa 2: Importar arquivos Swift para a classe ObjC

Em SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

O arquivo: <#YourProjectName#>-Swift.hjá deve ser criado automaticamente no seu projeto, mesmo que você não possa vê-lo.

Etapa 3: use sua classe

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];

NSLog(@"RetString: %@", retString);

Notas:

  1. Se a conclusão do código não estiver se comportando como o esperado, tente executar uma compilação rápida Rpara ajudar o Xcode a encontrar parte do código Objective-C em um contexto Swift e vice-versa.

  2. Se você adicionar um .swiftarquivo a um projeto mais antigo e receber o erro dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, tente reiniciar completamente o Xcode .

  3. Embora originalmente fosse possível usar classes Swift puras (não descendentes de NSObject) visíveis ao Objective-C usando o @objcprefixo, isso não é mais possível. Agora, para estar visível no Objective-C, o objeto Swift deve ser uma classe em conformidade NSObjectProtocol(a maneira mais fácil de fazer isso é herdar NSObject) ou ser enummarcado @objccom um valor bruto de algum tipo inteiro como Int. Você pode ver o histórico de edição de um exemplo de código Swift 1.x usando @objcsem essas restrições.

Logan
fonte
5
É importante que você anote métodos com os métodos @objc ou Swift não serão visíveis no Objective-C.
Tomáš Linhart
29
Você está certo. Você só precisará especificar se não usar objetos de cacau. Para ser acessível e utilizável no Objective-C, uma classe Swift deve ser descendente de uma classe Objective-C ou deve estar marcada como @objc.
Tomáš Linhart
2
@MarkusRautopuro - Entendi daqui: developer.apple.com/library/prerelease/ios/documentation/Swift/… "
Logan
2
Veja também: Sessão 406 da WWDC 2014: Integrando Swift ao Objective-C
Stuart M
6
Se estiver importando uma estrutura de Objective C para o Swift, importe todas as estruturas das quais a estrutura de Obj C depende em seu projeto (em Fases de construção -> Vincular binário com bibliotecas) e adicione # import's para aqueles em um arquivo de cabeçalho de prefixo, que deve ser adicionado ao seu projeto nas configurações de construção (no campo Cabeçalho do prefixo). Isso inclui estruturas como UIKit e Foundation, mesmo que elas já sejam usadas no Swift. Isso me tropeçou por horas, e ninguém parece ter documentado essas etapas.
usar o seguinte comando
121

Consulte o guia da Apple sobre o uso de Swift com cacau e Objective-C . Este guia aborda como usar os códigos Objective-C e C da Swift e vice-versa e contém recomendações sobre como converter um projeto ou misturar e combinar as partes Objective-C / C e Swift em um projeto existente.

O compilador gera automaticamente a sintaxe Swift para chamar funções C e métodos Objective-C. Como visto na documentação, este Objective-C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

se transforma neste código Swift:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

O Xcode também faz essa tradução rapidamente - você pode usar o Open Quickly ao editar um arquivo Swift e digitar um nome de classe Objective-C, e você será direcionado para uma versão Swift do cabeçalho da classe. (Você também pode obtê-lo clicando cmd em um símbolo da API em um arquivo Swift.) E toda a documentação de referência da API nas bibliotecas de desenvolvedores do iOS 8 e OS X v10.10 (Yosemite) é visível nas Objective-C e Swift formulários (por exemplo UIView).

rickster
fonte
3
O link direto para documentação da Apple como integrar Swift no projeto existente: developer.apple.com/library/prerelease/ios/documentation/Swift/...
skywinder
Se você estiver interessado em saber por que os arquivos de cabeçalho são necessários e como são usados ​​durante a fase de vinculação, leia este Manual Swift: Noções básicas sobre o pipeline de construção Swift / Objective-C
Honey
62

Aqui estão as instruções passo a passo para usar o código Objective-C (neste caso, uma estrutura fornecida por terceiros) em um projeto Swift:

  1. Adicione qualquer arquivo Objective-C ao seu projeto Swift escolhendo Arquivo -> Novo -> Novo arquivo -> Arquivo Objective-C. Ao salvar, o Xcode perguntará se você deseja adicionar um cabeçalho de ponte . Escolha ' Sim '. (fonte: derrrick.com )Gif: adicionando arquivo vazio ao projeto e gerando cabeçalho de ponte

Em etapas simples:

  1. Um prompt é exibido e, em seguida, clique em OK ... Se não aparecer, criamos manualmente como a seguir ... Crie um arquivo de cabeçalho a partir da fonte iOS e atribua o nome ProjectName-Bridging-Header (exemplo: Test -Bridging-Header) e, em seguida, vá para a configuração de compilação no código do compilador Swift -> ponte Objective-C adicione o nome da ponte Objective-C .. (Test / Test-Bridging-Header.h). Sim, está completo.

  2. Opcionalmente, exclua o arquivo Objective-C que você adicionou (nomeado "qualquer coisa" na imagem GIF acima). Você não precisa mais disso.

  3. Abra o arquivo de cabeçalho da ponte - o nome do arquivo está no formato [YourProject] -Bridging-Header.h . Ele inclui um comentário fornecido pelo Xcode. Adicione uma linha de código para o arquivo Objective-C que você deseja incluir , como uma estrutura de terceiros. Por exemplo, para adicionar o Mixpanel ao seu projeto, você precisará adicionar a seguinte linha de código ao arquivo de cabeçalho da ponte:

    #import "Mixpanel.h"
  4. Agora, em qualquer arquivo Swift, você pode usar o código Objective-C existente, na sintaxe Swift (no caso deste exemplo, e você pode chamar os métodos Mixpanel SDK, etc.). Você precisa se familiarizar com a forma como o Xcode converte Objective-C em Swift. O guia da Apple é uma leitura rápida. Ou veja esta resposta para um resumo incompleto.

Exemplo para Mixpanel:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}

É isso aí!

Nota: Se você remover o arquivo de cabeçalho de ponte do projeto , certifique-se de ir para Configurações de compilação e remova o valor de " Cabeçalho de ponte de objetivo-C " em "Swift Compiler - Generation de código".

derrrick
fonte
39

Você pode ler o belo post Swift & Cocoapods . Basicamente, precisamos criar um arquivo de cabeçalho de ponte e colocar todos os cabeçalhos de Objective-C lá. E então precisamos fazer referência a ele em nossas configurações de compilação. Depois disso, podemos usar o código Objective-C.

let manager = AFHTTPRequestOperationManager()
manager.GET(
  "http://example.com/resources.json",
  parameters: nil,
  success: { (operation: AFHTTPRequestOperation!,
              responseObject: AnyObject!) in
      println("JSON: " + responseObject.description)
  },
  failure: { (operation: AFHTTPRequestOperation!,
              error: NSError!) in
      println("Error: " + error.localizedDescription)
  })

Veja também o documento da Apple Using Swift with Cocoa e Objective-C também.

Jake Lin
fonte
25

Eu escrevi um projeto simples do Xcode 6 que mostra como misturar códigos C ++, Objective-C e Swift:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

Em particular, o exemplo chama uma função Objective-C e C ++ do Swift .

A chave é criar um cabeçalho compartilhado, Project-Bridging-Header.h, e colocar os cabeçalhos de Objective-C lá.

Faça o download do projeto como um exemplo completo.

Gian Luigi Romita
fonte
24

Mais uma coisa que gostaria de acrescentar aqui:

Sou muito grato pela resposta de @ Logan. Ajuda muito a criar um arquivo de ponte e configurações.

Mas depois de executar todas essas etapas, ainda não estou recebendo uma classe Objective-C no Swift.

Usei a cocoapodsbiblioteca e a integrei ao meu projeto. Qual é pod "pop".

Portanto, se você estiver usando pods de Objective-C no Swift, pode haver uma chance de que você não consiga obter importas classes no Swift.

A coisa simples que você precisa fazer é:

  1. Vá para o <YOUR-PROJECT>-Bridging-Headerarquivo e
  2. Substitua a instrução #import <ObjC_Framework>para@import ObjC_Framework

Por exemplo: (biblioteca pop)

Substituir

#import <pop/POP.h>

com

@import pop;

Use clang importquando #importnão estiver funcionando.

Kampai
fonte
Use a importação de clang quando #import não estiver funcionando. que? Não disse apenas que deveríamos usar @import ?!
Mel
22

Citações da documentação :

Qualquer estrutura Objective-C (ou biblioteca C) acessível como módulo pode ser importada diretamente no Swift. Isso inclui todas as estruturas do sistema Objective-C - como Foundation, UIKit e SpriteKit -, bem como bibliotecas C comuns fornecidas com o sistema. Por exemplo, para importar o Foundation, basta adicionar esta declaração de importação na parte superior do arquivo Swift em que você está trabalhando:

import Foundation

Essa importação disponibiliza todas as APIs da Foundation - incluindo NSDate, NSURL, NSMutableData e todos os seus métodos, propriedades e categorias - diretamente no Swift.

Gergo Erdosi
fonte
12

Apenas uma observação para quem está tentando adicionar uma biblioteca Objective-C ao Swift: Você deve adicionar -ObjC em Build Settings -> Linking -> Other Linker Flags .

david72
fonte
Por quê? Adicione informações sobre o que essa bandeira faz e por que ela deve ser adicionada.
Johan Karlsson
9

Depois de criar um cabeçalho Bridging, vá para Build Setting => Search for "Objective-C Bridging Header".

Logo abaixo, você encontrará o arquivo "" Objective-C Generated Interface Header Name "".

Importe esse arquivo no seu controlador de exibição.

Exemplo: No meu caso: "Dauble-Swift.h"

Descrição da imagem eEter aqui

Avijit Nagare
fonte
5

Clique no menu Novo arquivo e escolha o arquivo, selecione o idioma Objetivo. Naquele momento, ele gera automaticamente um arquivo "Objective-C Bridging Header" que é usado para definir algum nome de classe.

"Objective-C Bridging Header" em "Swift Compiler - Code Generation".

Yogesh shelke
fonte
3
  1. Crie um arquivo .h a partir de NewFile -> Origem -> arquivo de cabeçalho
  2. Em seguida, salve o nome do arquivo Your_Target_Name-Bridging-Header.h As pessoas aqui cometem erros comuns ao usar o nome do projeto, mas esse deve ser o nome do alvo do projeto se, caso os dois sejam diferentes, geralmente são iguais.
  3. Em seguida, nas configurações de construção, pesquise o sinalizador Objective-C Bridging Header e coloque o endereço do seu arquivo de ponte recém-criado, clique com o botão direito no arquivo -> show in finder -> arraste o arquivo na área de texto e o endereço será ser preenchido.
  4. Usando #import Your_Objective-C_file.h
  5. No arquivo rápido, você pode acessar o arquivo ObjC, mas apenas no idioma rápido.
Nish
fonte
3

insira a descrição da imagem aquiEu adicionei o projeto no github que inclui uma pequena amostra para chamar o código c objetivo da swift.

Chamar a classe ObjectiveC da swift

CrazyPro007
fonte
NOTA: - Quando você cria uma classe Objc em um projeto rápido, o xcode solicita uma ponte entre a classe automaticamente. Não se preocupe :)
CrazyPro007
3

No projeto Swift 4.2.1 no Xcode 10.1, você pode adicionar facilmente o arquivo Objective-C. Siga as etapas abaixo para conectar o arquivo Objective-C ao projeto Swift.

Etapa_01: Crie um novo projeto do Xcode usando o idioma Swift:

File> New> Project> objc.

Etapa_02: No projeto Swift, adicione um novo arquivo Objective-C:

File> New> File...> macOS> Objective-C File.

Etapa_03: Se você adicionar um novo arquivo Objective-C ao projeto Swift na primeira vez, o Xcode perguntará:

Would you like to configure an Objective-C bridging header?

insira a descrição da imagem aqui

Etapa_04: selecione a opção:

Create Bridging Header.

Etapa_05: Um arquivo correspondente será gerado com um nome:

Objc-Bridging-Header.h.

insira a descrição da imagem aqui

Etapa_06: Agora, você precisa configurar o caminho do arquivo Bridge no cabeçalho da ponte. No Navegador de projeto, clique no projeto com o nomeobjc e escolha:

Build Settings> Objective-C Bridging Header>Objc-Bridging-Header.h .

Etapa_07: arraste e solte seu Objc-Bridging-Header.hdentro dessa caixa para gerar um caminho de arquivo.

insira a descrição da imagem aqui

Etapa_08: Abra seu Objc-Bridging-Header.harquivo e importe o arquivo Objective-C que você deseja usar no seu arquivo Swift.

#import "SpecialObjcFile.m"

Aqui está um conteúdo de SpecialObjcFile.m:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

Etapa_09: Agora no seu arquivo Swift, você pode usar uma classe Objective-C:

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}

insira a descrição da imagem aqui insira a descrição da imagem aqui

Andy
fonte
1

Logans resposta do funciona bem, exceto nos últimos casos Swift 5, fornece algum erro do compilador. Aqui está a correção para as pessoas que estão trabalhando no Swift 5.

Swift 5

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val" as AnyObject

    override init() {}

    func someFunction(someArg:AnyObject) -> String {
        let returnVal = "You sent me \(someArg)"
        return returnVal
    }
}
Sazzad Hissain Khan
fonte
1

Consumidor rápido, produtor de Objective-C

  1. Adicionar um cabeçalho .he .marquivos de implementação - arquivo de classe Cocoa (Objective-C)
    Por exemploMyFileName

  2. configurar cabeçalho de ponte
    Quando você vê Would you like to configure an Objective-C bridging headerclique em - Sim

    • <target_name>-Bridging-Header.h será gerado automaticamente
    • Configurações de compilação -> Cabeçalho de ponte Objective-C
  3. Adicionar classe ao cabeçalho de ponte
    Em <target_name>-Bridging-Header.hadicionar uma linha#import "<MyFileName>.h"

PS Se você deve adicionar arquivos Objective-C existentes ao projeto Swift, adicione Bridging-Header.h antecipadamente

Consumidor Objective-C, produtor Swift

  1. Adicione um <MyFileName>.swifte estendaNSObject

  2. Importar arquivos Swift para a classe ObjC
    Adicione #import "<#YourProjectName#>-Swift.h"ao seu arquivo Objective-C

  3. Marcar código Swift público [@objc e @objcMembers]

yoAlex5
fonte
0

A Apple forneceu um guia oficial neste documento: como chamar-objetivo-código-c-código-de-swift

Aqui está a parte relevante:

Para importar um conjunto de arquivos Objective-C para o código Swift no mesmo destino de aplicativo, você depende de um arquivo de cabeçalho de ponte Objective-C para expor esses arquivos ao Swift . O Xcode se oferece para criar esse cabeçalho quando você adiciona um arquivo Swift a um aplicativo Objective-C existente ou um arquivo Objective-C a um aplicativo Swift existente.

Se você aceitar, o Xcode cria o arquivo de cabeçalho de ponte junto com o arquivo que você estava criando e o nomeia usando o nome do módulo do produto seguido de "-Bridging-Header.h". Como alternativa, você mesmo pode criar um cabeçalho de ponte escolhendo Arquivo> Novo> Arquivo> [sistema operacional]> Origem> Arquivo de cabeçalho

Edite o cabeçalho da ponte para expor seu código Objective-C ao seu código Swift:

  1. No cabeçalho de ponte Objective-C, importe todos os cabeçalhos de Objective-C que você deseja expor para o Swift .
  2. Em Configurações de compilação, no Swift Compiler - Geração de código, verifique se a configuração de compilação do cabeçalho de ponte Objective-C possui um caminho para o arquivo de cabeçalho da ponte. O caminho deve ser relativo ao seu projeto, semelhante à maneira como o caminho Info.plist é especificado em Configurações de compilação. Na maioria dos casos, você não precisará modificar essa configuração.

Quaisquer cabeçalhos públicos do Objective-C listados no cabeçalho da ponte são visíveis para o Swift.

Tibin Thomas
fonte
0

Abordagem bidirecional para usar o objetivo-c objetivo-c

1

  1. Criar arquivo bridge-header.h no projeto Xcode
  2. importar arquivo .h no arquivo bridge-Header
  3. Defina o caminho do bridge-Header nas configurações de compilação.
  4. Limpe o projeto

2

  1. Crie arquivos objetivo-c no projeto (ele define automaticamente o caminho nas Configurações de compilação para você)
  2. importar arquivo .h no arquivo bridge-Header

Agora é bom ir Obrigado

Sanjay Mali
fonte