Come posso chiamare il codice Objective-C da Swift?


974

In Swift, come si chiama il codice Objective-C?

Apple ha affermato che potrebbero coesistere in una sola applicazione, ma ciò significa che si potrebbero riutilizzare tecnicamente vecchie classi realizzate in Objective-C mentre si creano nuove classi in Swift?




10
Interessante che questa domanda ottenga così tanti voti positivi e una generosità. Quando l'ho visto per la prima volta ho pensato: RTFM. Come si è visto, non mostra davvero alcuna ricerca in quanto attualmente ci sono solo due o tre risorse che documentano ufficialmente Swift, e una di queste è interamente dedicata a questo (ed è collegata nel primo commento).
File analogico

6
@EvolGate: cosa manca esattamente all'obiettivo C che gli impedisce di essere un linguaggio indipendente dalla piattaforma? Le librerie della lingua e della lingua standard sono open source. Puoi utilizzare Objective C in e per Windows, Os X, Linux, BSD, Solaris e qualsiasi altra piattaforma supportata da GCC o LLVM. Puoi facilmente portare l'Obiettivo C su qualsiasi piattaforma con un compilatore C decente anche se non è supportato da GCC né da LLVM. Non vedo come potrebbe essere più indipendente dalla piattaforma di questo.
File analogico

2
@DavidMulder: è ancora necessaria la sezione "Il ragionamento"?
franck,

Risposte:


1395

Utilizzo delle classi Objective-C in Swift

Se hai una classe esistente che desideri utilizzare, esegui il passaggio 2 e vai al passaggio 5 . (Per alcuni casi, ho dovuto aggiungere un esplicito #import <Foundation/Foundation.ha un vecchio file Objective-C.)

Passaggio 1: aggiungere l'implementazione di Objective-C - .m

Aggiungi un .mfile alla tua classe e chiamalo CustomObject.m.

Passaggio 2: Aggiungi intestazione ponte

Quando aggiungi il tuo .mfile, verrai probabilmente colpito con un prompt simile al seguente:

Una finestra di dialogo stile foglio macOS di Xcode che chiede se si desidera "configurare un'intestazione di bridge Objective-C"

Fai clic su !

Se il prompt non è stato visualizzato o è stata eliminata accidentalmente l'intestazione del ponte, aggiungere un nuovo .hfile al progetto e denominarlo <#YourProjectName#>-Bridging-Header.h.

In alcune situazioni, in particolare quando si lavora con framework Objective-C, non si aggiunge esplicitamente una classe Objective-C e Xcode non riesce a trovare il linker. In questo caso, crea il tuo .hfile come indicato sopra, quindi assicurati di collegare il suo percorso nelle impostazioni del progetto di destinazione in questo modo:

Un'animazione che dimostra il paragrafo precedente

Nota:

È consigliabile collegare il progetto utilizzando la $(SRCROOT)macro in modo che se si sposta il progetto o ci si lavora con altri utilizzando un repository remoto, funzionerà comunque. $(SRCROOT)può essere pensato come la directory che contiene il tuo file .xcodeproj. Potrebbe apparire così:

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

Passaggio 3: Aggiungi intestazione Objective-C - .h

Aggiungi un altro .hfile e chiamalo CustomObject.h.

Passaggio 4: crea la tua classe Objective-C

In CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

In CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

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

@end

Passaggio 5: aggiungere classe a Bridging-Header

In YourProject-Bridging-Header.h:

#import "CustomObject.h"

Passaggio 6: usa il tuo oggetto

In SomeSwiftFile.swift:

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

Non è necessario importare esplicitamente; ecco a cosa serve l'intestazione ponte.

Utilizzo delle classi Swift in Objective-C

Passaggio 1: creare una nuova classe Swift

Aggiungi un .swiftfile al tuo progetto e chiamalo MySwiftObject.swift.

In 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)"
    }
}

Passaggio 2: importare i file Swift nella classe ObjC

In SomeRandomClass.m:

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

Il file: <#YourProjectName#>-Swift.hdovrebbe già essere creato automaticamente nel tuo progetto, anche se non riesci a vederlo.

Passaggio 3: usa la tua 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);

Appunti:

  1. Se il completamento del codice non si comporta come previsto, prova a eseguire una build rapida Rper aiutare Xcode a trovare parte del codice Objective-C da un contesto Swift e viceversa.

  2. Se aggiungi un .swiftfile a un progetto precedente e ricevi l'errore dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, prova a riavviare completamente Xcode .

  3. Sebbene in origine fosse possibile utilizzare classi Swift pure (non discendenti di NSObject) che sono visibili a Objective-C usando il @objcprefisso, ciò non è più possibile. Ora, per essere visibile in Objective-C, l'oggetto Swift deve essere o una classe conforme a NSObjectProtocol(il modo più semplice per farlo è ereditare da NSObject), oppure essere enumcontrassegnato @objccon un valore grezzo di un tipo intero come Int. È possibile visualizzare la cronologia delle modifiche per un esempio di codice Swift 1.x utilizzando @objcsenza queste restrizioni.


5
È importante annotare i metodi con i metodi @objc o Swift che non saranno visibili da Objective-C.
Tomáš Linhart,

29
Hai ragione. Devi solo specificarlo se non usi oggetti Cocoa. Per essere accessibile e utilizzabile in Objective-C, una classe Swift deve essere un discendente di una classe Objective-C oppure deve essere contrassegnata con @objc.
Tomáš Linhart,


2
Vedi anche: WWDC 2014 Sessione 406: Integrazione di Swift con Objective-C
Stuart M

6
Se si importa un framework Objective C in Swift, assicurarsi di importare tutti i framework da cui dipende il framework Obj C nel proprio progetto (in Build Phases -> Link Binary With Libraries), quindi aggiungere # import per quelli a un file di intestazione prefisso, che deve essere aggiunto al progetto nelle impostazioni di creazione (nel campo Intestazione prefisso). Ciò include framework come UIKit e Foundation, anche se quelli sono già utilizzati all'interno di Swift. Questo mi ha fatto inciampare per ore e nessuno sembra aver documentato questi passaggi.
user1021430

121

Consulta la guida di Apple sull'utilizzo di Swift con Cocoa e Objective-C . Questa guida illustra come utilizzare i codici Objective-C e C di Swift e viceversa e contiene raccomandazioni su come convertire un progetto o mescolare e abbinare parti Objective-C / C e Swift in un progetto esistente.

Il compilatore genera automaticamente la sintassi Swift per chiamare le funzioni C e i metodi Objective-C. Come visto nella documentazione, questo Obiettivo-C:

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

si trasforma in questo codice Swift:

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

Xcode esegue anche questa traduzione al volo: puoi usare Apri rapidamente durante la modifica di un file Swift e digitare un nome di classe Objective-C, e ti porterà a una versione di Swift-ified dell'intestazione della classe. (Puoi anche ottenere questo facendo clic su cmd facendo clic su un simbolo API in un file Swift.) E tutta la documentazione di riferimento API nelle librerie per sviluppatori iOS 8 e OS X v10.10 (Yosemite) è visibile in Objective-C e Swift moduli (ad es UIView.).


3
Il collegamento diretto alla documentazione Apple su come integrare Swift nel progetto esistente: developer.apple.com/library/prerelease/ios/documentation/Swift/…
skywinder

Se sei interessato al motivo per cui sono necessari i file di intestazione e come viene utilizzato durante la fase di collegamento, assicurati di leggere questo manuale Swift: Comprendere la pipeline di Swift / Objective-C
Honey

62

Ecco le istruzioni dettagliate per l'uso del codice Objective-C (in questo caso, un framework fornito da una terza parte) in un progetto Swift:

  1. Aggiungi qualsiasi file Objective-C al tuo progetto Swift selezionando File -> Nuovo -> Nuovo file -> File Objective-C. Al momento del salvataggio, Xcode ti chiederà se desideri aggiungere un'intestazione a ponte . Scegli " ". (fonte: derrrick.com )Gif: aggiunta di file vuoto al progetto e generazione di header bridging

In semplici passaggi:

  1. Viene visualizzato un prompt, quindi fare clic su OK ... Se non viene visualizzato, lo creiamo manualmente come nel seguente ... Crea un file di intestazione dall'origine iOS e diamo il nome ProjectName-Bridging-Header (esempio: Test -Bridging-Header), quindi vai a costruire l'impostazione nel codice del compilatore Swift -> Objective-C bridge aggiungi il nome del bridge Objective-C .. (Test / Test-Bridging-Header.h). Sì, è completo.

  2. Facoltativamente, elimina il file Objective-C che hai aggiunto (chiamato "qualsiasi cosa" nell'immagine GIF sopra). Non ne hai più bisogno.

  3. Apri il file di intestazione ponte - il nome del file è nel formato [YourProject] -Bridging-Header.h . Include un commento fornito da Xcode. Aggiungi una riga di codice per il file Objective-C che desideri includere , ad esempio un framework di terze parti. Ad esempio, per aggiungere Mixpanel al tuo progetto, dovrai aggiungere la seguente riga di codice al file di intestazione ponte:

    #import "Mixpanel.h"
  4. Ora in qualsiasi file Swift puoi usare il codice Objective-C esistente, nella sintassi Swift (nel caso di questo esempio, e puoi chiamare i metodi Mixpanel SDK, ecc.). Devi familiarizzare con il modo in cui Xcode traduce Objective-C in Swift. La guida di Apple è una lettura veloce. Oppure vedi questa risposta per un riepilogo incompleto.

Esempio per Mixpanel:

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

Questo è tutto!

Nota: se rimuovi il file di intestazione ponte dal tuo progetto , assicurati di andare in Impostazioni di costruzione e rimuovere il valore per " Intestazione ponte obiettivo-C " in "Compilatore rapido - Generazione di codice".


39

Puoi leggere il bel post Swift & Cocoapods . Fondamentalmente, dobbiamo creare un file di intestazione a ponte e inserire lì tutte le intestazioni di Objective-C. E quindi dobbiamo fare riferimento alle nostre impostazioni di compilazione. Successivamente, possiamo usare il codice 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)
  })

Dai un'occhiata anche al documento di Apple Utilizzo di Swift con Cocoa e Objective-C .



24

Un'altra cosa che vorrei aggiungere qui:

Sono molto grato per la risposta di @ Logan. Aiuta molto a creare un file bridge e configurazioni.

Ma dopo aver fatto tutti questi passaggi non sto ancora ottenendo una classe Objective-C in Swift.

Ho usato la cocoapodsbiblioteca e l'ho integrata nel mio progetto. Quale è pod "pop".

Quindi, se stai utilizzando i pod Objective-C in Swift, potrebbe esserci la possibilità che non riesci a ottenere o importle classi in Swift.

La cosa semplice che devi fare è:

  1. Vai al <YOUR-PROJECT>-Bridging-Headerfile e
  2. Sostituisci la dichiarazione #import <ObjC_Framework>a@import ObjC_Framework

Ad esempio: (Libreria pop)

Sostituire

#import <pop/POP.h>

con

@import pop;

Utilizzare clang importquando #importnon funziona.


Usa clang import quando #import non funziona. che cosa? Non hai semplicemente detto che dovremmo usare @import ?!
Miele

22

Citazione dalla documentazione :

Qualsiasi framework Objective-C (o libreria C) accessibile come modulo può essere importato direttamente in Swift. Ciò include tutti i framework di sistema Objective-C, come Foundation, UIKit e SpriteKit, nonché le librerie C comuni fornite con il sistema. Ad esempio, per importare Foundation, aggiungi semplicemente questa istruzione import nella parte superiore del file Swift in cui stai lavorando:

import Foundation

Questa importazione rende tutte le API di Foundation, inclusi NSDate, NSURL, NSMutableData e tutti i loro metodi, proprietà e categorie, direttamente disponibili in Swift.


12

Solo una nota per chiunque stia cercando di aggiungere una libreria Objective-C a Swift: dovresti aggiungere -ObjC in Impostazioni build -> Collegamento -> Altre bandiere linker .


Perché? Aggiungi informazioni su ciò che fa questo flag e perché dovrebbe essere aggiunto.
Johan Karlsson,

9

Dopo aver creato un'intestazione Bridging, vai a Build Setting => Cerca "Objective-C Bridging Header".

Di seguito è riportato il file "" Nome intestazione interfaccia generazione Objective-C ".

Importa quel file nel tuo controller di visualizzazione.

Esempio: nel mio caso: "Dauble-Swift.h"

eEter descrizione dell'immagine qui


5

Fai clic sul menu Nuovo file e scegli la lingua di selezione del file Obiettivo. In quel momento genera automaticamente un file "Objective-C Bridging Header" che viene utilizzato per definire un nome di classe.

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


3
  1. Crea un file .h da NewFile -> Source -> file header
  2. Quindi salva il nome del file Your_Target_Name-Bridging-Header.h Le persone qui ottengono un errore comune prendendo il nome del loro progetto ma dovrebbe essere il nome del Target del progetto se nel caso entrambi siano diversi, generalmente sono uguali.
  3. Quindi, nelle impostazioni di creazione, cerca il flag di intestazione Bridging Objective-C e inserisci l'indirizzo del tuo file di bridge appena creato, puoi farlo con il tasto destro del mouse sul file -> mostra nel finder -> trascina il file nell'area di testo quindi l'indirizzo sarà essere popolato.
  4. Usando #import Your_Objective-C_file.h
  5. Nel file rapido è possibile accedere al file ObjC ma solo in una lingua veloce.


3

Nel progetto Swift 4.2.1 in Xcode 10.1 è possibile aggiungere facilmente il file Objective-C. Seguire i passaggi seguenti per collegare il file Objective-C al progetto Swift.

Step_01: crea un nuovo progetto Xcode usando la lingua Swift:

File> New> Project> objc.

Step_02: nel progetto Swift aggiungi il nuovo file Objective-C:

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

Step_03: Se aggiungi un nuovo file Objective-C nel progetto Swift per la prima volta, Xcode ti chiede:

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

inserisci qui la descrizione dell'immagine

Step_04: seleziona l'opzione:

Create Bridging Header.

Step_05: verrà generato un file corrispondente con un nome:

Objc-Bridging-Header.h.

inserisci qui la descrizione dell'immagine

Step_06: ora è necessario impostare il percorso del file Bridge nell'intestazione del bridge. In Project Navigator fai clic sul progetto con il nome objce quindi scegli:

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

Step_07: trascina la selezione Objc-Bridging-Header.hin quella casella per generare un percorso di file.

inserisci qui la descrizione dell'immagine

Step_08: apri il tuo Objc-Bridging-Header.hfile e importa il file Objective-C che vuoi usare nel tuo file Swift.

#import "SpecialObjcFile.m"

Ecco un contenuto di SpecialObjcFile.m:

#import <Foundation/Foundation.h>

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

Step_09: ora nel tuo file Swift, puoi utilizzare una classe Objective-C:

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

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


1

La risposta di Logans funziona benissimo tranne che in ultimo Swift 5fornisce alcuni errori del compilatore. Ecco la soluzione per le persone che stanno lavorando su 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
    }
}

1

Consumatore rapido, produttore di Objective-C

  1. Aggiungi un'intestazione .he .mfile di implementazione - File di classe Cocoa (Objective-C)
    Ad esempioMyFileName

  2. configura intestazione ponte
    Quando vedi Would you like to configure an Objective-C bridging headerclic -

    • <target_name>-Bridging-Header.h verrà generato automaticamente
    • Crea impostazioni -> Intestazione ponte Objective-C
  3. Aggiungi classe a Bridging-Header
    In <target_name>-Bridging-Header.haggiungi una linea#import "<MyFileName>.h"

PS Se è necessario aggiungere file Objective-C esistenti nel progetto Swift, aggiungere Bridging-Header.hprima

Consumatore Objective-C, produttore Swift

  1. Aggiungi a <MyFileName>.swifted estendeNSObject

  2. Importa file Swift in classe ObjC
    Aggiungi #import "<#YourProjectName#>-Swift.h"al tuo file Objective-C

  3. Contrassegna codice Swift pubblico [@objc e @objcMembers]


0

Apple ha fornito una guida ufficiale in questo documento: how-to-call-goal-c-code-from-swift

Ecco la parte rilevante:

Per importare un set di file Objective-C nel codice Swift all'interno della stessa destinazione dell'app, fai affidamento su un file header dell'intestazione Bridge Objective-C per esporre tali file a Swift . Xcode offre di creare questa intestazione quando aggiungi un file Swift a un'app Objective-C esistente o un file Objective-C a un'app Swift esistente.

Se accetti, Xcode crea il file di intestazione ponte insieme al file che stavi creando e lo nomina usando il nome del modulo del prodotto seguito da "-Bridging-Header.h". In alternativa, puoi creare tu stesso un'intestazione a ponte scegliendo File> Nuovo> File> [sistema operativo]> Origine> File di intestazione

Modifica l'intestazione ponte per esporre il tuo codice Objective-C al tuo codice Swift:

  1. Nella tua intestazione ponte Objective-C, importa tutte le intestazioni Objective-C che vuoi esporre a Swift .
  2. In Impostazioni di compilazione, in Swift Compiler - Generazione di codice, assicurati che l'impostazione di build Intestazione Bridging di Objective-C abbia un percorso al file di intestazione di bridging. Il percorso dovrebbe essere relativo al tuo progetto, in modo simile al modo in cui il percorso Info.plist è specificato nelle Impostazioni di costruzione. Nella maggior parte dei casi, non è necessario modificare questa impostazione.

Tutte le intestazioni pubbliche di Objective-C elencate nell'intestazione bridge sono visibili a Swift.


0

Approccio bidirezionale per usare goal-c goal-c

1

  1. Crea il file bridge-header.h in Xcode Project
  2. importa il file .h nel file bridge-Header
  3. Imposta il percorso dell'intestazione del ponte nelle impostazioni di creazione.
  4. Pulisci il progetto

2

  1. Crea file object-c nel progetto (imposta automaticamente il percorso in Build Settings per te)
  2. importa il file .h nel file bridge-Header

Ora va bene Grazie

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.