Bagaimana cara saya memanggil kode Objective-C dari Swift?

974

Di Swift, bagaimana seseorang memanggil kode Objective-C?

Apple menyebutkan bahwa mereka dapat hidup berdampingan dalam satu aplikasi, tetapi apakah ini berarti bahwa seseorang secara teknis dapat menggunakan kembali kelas lama yang dibuat di Objective-C sambil membangun kelas baru di Swift?

David Mulder
sumber
13
Lihat panduan Apple untuk Menggunakan Swift dengan Kakao dan Objective-C .
rickster
10
Menarik bahwa pertanyaan ini mendapat begitu banyak upvotes dan hadiah. Ketika saya pertama kali melihatnya, saya hanya berpikir: RTFM. Seperti yang ditunjukkan itu benar-benar tidak menunjukkan penelitian karena saat ini hanya ada dua atau tiga sumber yang secara resmi mendokumentasikan Swift, dan salah satu dari mereka sepenuhnya didedikasikan untuk hal ini (dan terkait dengan komentar pertama).
File Analog
6
@Volgate: persis apa yang hilang dari Objective C yang mencegahnya menjadi bahasa platform independen? Perpustakaan bahasa dan standar bahasa adalah open source. Anda dapat menggunakan Objective C di dan untuk Windows, Os X, Linux, BSD, Solaris dan platform lainnya yang didukung oleh GCC atau LLVM. Anda dapat dengan mudah mem-porting Objective C ke platform apa pun dengan kompiler C yang layak meskipun didukung oleh GCC atau LLVM. Saya tidak melihat bagaimana ini bisa lebih mandiri dari platform ini.
File Analog
2
@ Davidvidul: Apakah bagian "Penalaran" masih diperlukan?
franck

Jawaban:

1395

Menggunakan Kelas Objective-C di Swift

Jika Anda memiliki kelas yang sudah ada yang ingin Anda gunakan, lakukan Langkah 2 dan kemudian lewati ke Langkah 5 . (Untuk beberapa kasus, saya harus menambahkan eksplisit #import <Foundation/Foundation.hke File Objective-C yang lebih lama.)

Langkah 1: Tambahkan Implementasi Objective-C - .m

Tambahkan .mfile ke kelas Anda, dan beri nama CustomObject.m.

Langkah 2: Tambahkan Bridging Header

Saat menambahkan .mfile Anda, Anda akan dipukul dengan prompt yang terlihat seperti ini:

Dialog style sheet macOS dari Xcode menanyakan apakah Anda "ingin mengkonfigurasi header bridging Objective-C"

Klik Ya !

Jika Anda tidak melihat prompt, atau secara tidak sengaja menghapus header bridging Anda, tambahkan .hfile baru ke proyek Anda dan beri nama<#YourProjectName#>-Bridging-Header.h .

Dalam beberapa situasi, terutama ketika bekerja dengan kerangka kerja Objective-C, Anda tidak menambahkan kelas Objective-C secara eksplisit dan Xcode tidak dapat menemukan tautan. Dalam hal ini, buat .hfile Anda dengan nama yang disebutkan di atas, lalu pastikan Anda menautkan lintasannya di pengaturan proyek target Anda seperti:

Animasi yang menunjukkan paragraf di atas

catatan:

Praktik terbaik untuk menautkan proyek Anda menggunakan $(SRCROOT)makro sehingga jika Anda memindahkan proyek Anda, atau mengerjakannya dengan orang lain menggunakan repositori jarak jauh, itu akan tetap berfungsi. $(SRCROOT)dapat dianggap sebagai direktori yang berisi file .xcodeproj Anda. Mungkin terlihat seperti ini:

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

Langkah 3: Tambahkan Header Objective-C - .h

Tambahkan .hfile lain dan beri namaCustomObject.h .

Langkah 4: Bangun Kelas Objective-C Anda

Di CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

Di CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

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

@end

Langkah 5: Tambahkan Kelas ke Bridging-Header

Dalam YourProject-Bridging-Header.h:

#import "CustomObject.h"

Langkah 6: Gunakan Objek Anda

Dalam SomeSwiftFile.swift:

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

Tidak perlu mengimpor secara eksplisit; itulah gunanya header penghubung.

Menggunakan Kelas Swift di Objective-C

Langkah 1: Buat Kelas Swift Baru

Tambahkan .swiftfile ke proyek Anda, dan beri nama MySwiftObject.swift.

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

Langkah 2: Impor File Swift ke ObjC Class

Dalam SomeRandomClass.m:

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

File: <#YourProjectName#>-Swift.hseharusnya sudah dibuat secara otomatis di proyek Anda, bahkan jika Anda tidak dapat melihatnya.

Langkah 3: Gunakan kelas Anda

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);

Catatan:

  1. Jika Penyelesaian Kode tidak berlaku seperti yang Anda harapkan, coba jalankan build cepat dengan Runtuk membantu Xcode menemukan beberapa kode Objective-C dari konteks Swift dan sebaliknya.

  2. Jika Anda menambahkan .swiftfile ke proyek yang lebih lama dan mendapatkan kesalahan dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, coba restart Xcode sepenuhnya .

  3. Meskipun pada awalnya dimungkinkan untuk menggunakan kelas Swift murni (Bukan turunan NSObject) yang terlihat oleh Objective-C dengan menggunakan @objcawalan, ini tidak lagi mungkin. Sekarang, agar terlihat di Objective-C, objek Swift harus berupa kelas yang sesuai NSObjectProtocol(cara termudah untuk melakukan ini adalah mewarisi dari NSObject), atau enumditandai @objcdengan nilai mentah dari beberapa tipe integer seperti Int. Anda dapat melihat histori edit untuk contoh kode Swift 1.x menggunakan @objctanpa batasan ini.

Logan
sumber
5
Penting Anda perlu membuat anotasi metode dengan @objc atau metode Swift tidak akan terlihat dari Objective-C.
Tomáš Linhart
29
Kamu benar. Anda hanya perlu menentukannya jika Anda tidak menggunakan objek Kakao. Agar dapat diakses dan digunakan dalam Objective-C, kelas Swift harus merupakan turunan dari kelas Objective-C atau harus ditandai @objc.
Tomáš Linhart
2
@MarkusRautopuro - Dapat dari sini: developer.apple.com/library/prerelease/ios/documentation/Swift/… "
Logan
2
Lihat juga: WWDC 2014 Sesi 406: Mengintegrasikan Swift dengan Objective-C
Stuart M
6
Jika mengimpor kerangka kerja Objective C ke Swift, pastikan untuk mengimpor semua kerangka kerja yang tergantung pada kerangka kerja CJ ke dalam proyek Anda (dalam Bangun Fase -> Tautkan Biner Dengan Perpustakaan), lalu tambahkan # import untuk yang ke file header awalan, yang harus ditambahkan ke proyek Anda dalam pengaturan build (di bidang Prefix Header). Ini termasuk kerangka kerja seperti UIKit dan Foundation, bahkan jika itu sudah digunakan dari dalam Swift. Ini membuat saya tersandung selama berjam-jam, dan sepertinya tidak ada yang mendokumentasikan langkah-langkah ini.
user1021430
121

Lihat panduan Apple untuk Menggunakan Swift dengan Kakao dan Objective-C . Panduan ini mencakup cara menggunakan kode Objective-C dan C dari Swift dan sebaliknya dan memiliki rekomendasi untuk cara mengkonversi proyek atau mencampur dan mencocokkan Objective-C / C dan bagian Swift dalam proyek yang ada.

Compiler secara otomatis menghasilkan sintaks Swift untuk memanggil fungsi C dan metode Objective-C. Seperti yang terlihat dalam dokumentasi, Objective-C ini:

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

berubah menjadi kode Swift ini:

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

Xcode juga melakukan terjemahan ini dengan cepat - Anda dapat menggunakan Open Quickly saat mengedit file Swift dan ketik nama kelas Objective-C, dan itu akan membawa Anda ke versi header kelas Swift-ified dari header kelas. (Anda juga bisa mendapatkan ini dengan mengklik cmd pada simbol API di file Swift.) Dan semua dokumentasi referensi API di iOS 8 dan OS X v10.10 (Yosemite) perpustakaan pengembang terlihat di Objective-C dan Swift formulir (misalnya UIView).

rickster
sumber
3
Tautan langsung ke dokumentasi Apple cara mengintegrasikan Swift dalam proyek yang ada: developer.apple.com/library/prerelease/ios/documentation/Swift/…
skywinder
Jika kami tertarik tentang mengapa file header diperlukan dan bagaimana digunakan selama fase penautan, maka pastikan Anda membaca Manual Swift: Memahami Swift / Objective-C Build Pipeline
Honey
62

Berikut adalah petunjuk langkah demi langkah untuk menggunakan kode Objective-C (dalam hal ini, kerangka kerja yang disediakan oleh pihak ketiga) dalam proyek Swift:

  1. Tambahkan file Objective-C ke proyek Swift Anda dengan memilih File -> New -> File Baru -> File Objective-C. Setelah menyimpan, Xcode akan menanyakan apakah Anda ingin menambahkan header bridging . Pilih ' Ya '. (sumber: derrrick.com )Gif: menambahkan file kosong ke proyek dan menghasilkan bridging header

Dalam langkah-langkah sederhana:

  1. Sebuah prompt muncul, dan kemudian klik OK ... Jika tidak muncul, maka kami membuatnya secara manual seperti berikut ini ... Buat satu file header dari sumber iOS dan beri nama ProjectName-Bridging-Header (contoh: Tes -Bridging-Header), dan kemudian pergi untuk membangun pengaturan dalam kode kompiler Swift -> Objective-C bridge menambahkan nama jembatan Objective-C .. (Test / Test-Bridging-Header.h). Ya, itu lengkap.

  2. Secara opsional, hapus file Objective-C yang Anda tambahkan (beri nama "apa pun" pada gambar GIF di atas). Anda tidak membutuhkannya lagi.

  3. Buka file header bridging - nama file dalam bentuk [Proyek Anda] -Bridging-Header.h . Ini termasuk komentar yang disediakan Xcode. Tambahkan satu baris kode untuk file Objective-C yang ingin Anda sertakan , seperti kerangka kerja pihak ketiga. Misalnya, untuk menambahkan Mixpanel ke proyek Anda, Anda harus menambahkan baris kode berikut ke file header bridging:

    #import "Mixpanel.h"
  4. Sekarang dalam file Swift apa saja Anda dapat menggunakan kode Objective-C yang ada, dalam sintaks Swift (dalam kasus contoh ini, dan Anda dapat memanggil metode Mixpanel SDK, dll.). Anda perlu membiasakan diri dengan bagaimana Xcode menerjemahkan Objective-C ke Swift. Panduan Apple adalah bacaan cepat. Atau lihat jawaban ini untuk ringkasan yang tidak lengkap.

Contoh untuk Mixpanel:

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

Itu dia!

Catatan: Jika Anda menghapus file header bridging dari proyek Anda , pastikan untuk masuk ke Pengaturan Bangun dan menghapus nilai untuk " Header Bridging Objective-C " di bawah "Swift Compiler - Pembuatan Kode".

derrrick
sumber
39

Anda dapat membaca pos yang bagus Swift & Cocoapods . Pada dasarnya, kita perlu membuat file header bridging dan meletakkan semua header Objective-C di sana. Dan kemudian kita perlu referensi dari pengaturan build kita. Setelah itu, kita bisa menggunakan kode 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)
  })

Lihat juga dokumen Apple Menggunakan Swift dengan Kakao dan Objective-C juga.

Jake Lin
sumber
25

Saya menulis proyek Xcode 6 sederhana yang menunjukkan cara mencampur kode C ++, Objective-C dan Swift:

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

Secara khusus, contoh memanggil fungsi Objective-C dan C ++ dari Swift .

Kuncinya adalah membuat header bersama, Project-Bridging-Header.h, dan meletakkan header Objective-C di sana.

Silakan unduh proyek sebagai contoh lengkap.

Gian Luigi Romita
sumber
24

Satu hal lagi yang ingin saya tambahkan di sini:

Saya sangat berterima kasih atas jawaban @ Logan. Ini sangat membantu untuk membuat file jembatan dan pengaturan.

Tetapi setelah melakukan semua langkah ini saya masih belum mendapatkan kelas Objective-C di Swift.

Saya menggunakan cocoapodsperpustakaan dan mengintegrasikannya ke dalam proyek saya. Yang mana pod "pop".

Jadi jika Anda menggunakan pod Objective-C di Swift maka mungkin ada kemungkinan Anda tidak bisa mendapatkan atau importkelas menjadi Swift.

Hal sederhana yang harus Anda lakukan adalah:

  1. Buka <YOUR-PROJECT>-Bridging-Headerfile dan
  2. Ganti pernyataan #import <ObjC_Framework>ke@import ObjC_Framework

Misalnya: (Pustaka pop)

Menggantikan

#import <pop/POP.h>

dengan

@import pop;

Gunakan clang importsaat #importtidak bekerja.

Kampai
sumber
Gunakan impor dentang saat #import tidak berfungsi. apa? Tidak hanya mengatakan kita harus menggunakan @import ?!
Sayang
22

Kutipan dari dokumentasi :

Kerangka Objective-C (atau pustaka C) apa pun yang dapat diakses sebagai modul dapat diimpor langsung ke Swift. Ini termasuk semua kerangka kerja sistem Objective-C — seperti Foundation, UIKit, dan SpriteKit — serta pustaka C umum yang disertakan dengan sistem. Misalnya, untuk mengimpor Yayasan, cukup tambahkan pernyataan impor ini di bagian atas file Swift yang Anda kerjakan:

import Foundation

Impor ini membuat semua API Foundation — termasuk NSDate, NSURL, NSMutableData, dan semua metode, properti, dan kategorinya — tersedia langsung di Swift.

Gergo Erdosi
sumber
12

Hanya catatan untuk siapa pun yang mencoba menambahkan pustaka Objective-C ke Swift: Anda harus menambahkan -ObjC di Pengaturan Bangun -> Menautkan -> Bendera Tautan Lainnya .

david72
sumber
Mengapa? Harap tambahkan informasi tentang apa yang dilakukan bendera ini dan mengapa bendera itu harus ditambahkan.
Johan Karlsson
9

Setelah Anda membuat header Bridging, pergi ke Build Setting => Cari "Header Bridging Objective-C".

Tepat di bawah Anda akan menemukan file "" Objective-C Generated Interface Header Name ".

Impor file itu di controller tampilan Anda.

Contoh: Dalam kasus saya: "Dauble-Swift.h"

deskripsi gambar eEter di sini

Avijit Nagare
sumber
5

Klik pada menu File baru , dan pilih bahasa pilih file Objective. Pada saat itu secara otomatis menghasilkan file "Objective-C Bridging Header" yang digunakan untuk mendefinisikan beberapa nama kelas.

"Objective-C Bridging Header" di bawah "Swift Compiler - Code Generation".

Yogesh Shelke
sumber
3
  1. Buat file .h dari NewFile -> Source -> file header
  2. Kemudian simpan nama file Your_Target_Name-Bridging-Header.h Orang - orang di sini mendapatkan kesalahan umum dengan mengambil nama proyek mereka tetapi itu harus menjadi nama Target Proyek jika dalam kasus keduanya berbeda, umumnya mereka sama.
  3. Kemudian dalam membangun pengaturan mencari Objective-C Bridging Header bendera dan letakkan alamat file bridging yang baru Anda buat, Anda dapat melakukannya dengan klik kanan pada file -> show in finder -> seret file di area teks kemudian alamat tersebut akan diisi
  4. Menggunakan #import Your_Objective-C_file.h
  5. Dalam file cepat Anda dapat mengakses file ObjC tetapi hanya dalam bahasa cepat.
Nish
sumber
3

masukkan deskripsi gambar di siniSaya telah menambahkan proyek pada github yang menyertakan sampel kecil untuk memanggil kode c objektif dari swift.

Panggil kelas ObjectiveC dari swift

CrazyPro007
sumber
CATATAN: - Ketika Anda membuat kelas Objc dalam proyek cepat daripada xcode meminta menjembatani kelas secara otomatis. Jangan khawatir :)
CrazyPro007
3

Dalam proyek Swift 4.2.1 di Xcode 10.1 Anda dapat dengan mudah menambahkan file Objective-C. Ikuti langkah-langkah di bawah ini untuk menjembatani file Objective-C ke proyek Swift.

Step_01: Buat proyek Xcode baru menggunakan bahasa Swift:

File> New> Project> objc.

Step_02: Dalam proyek Swift tambahkan file Objective-C baru:

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

Step_03: Jika Anda menambahkan file Objective-C baru ke proyek Swift pada saat pertama kali, Xcode meminta Anda:

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

masukkan deskripsi gambar di sini

Step_04: Pilih opsi:

Create Bridging Header.

Step_05: File yang sesuai akan dihasilkan dengan nama:

Objc-Bridging-Header.h.

masukkan deskripsi gambar di sini

Step_06: Sekarang, Anda perlu mengatur path file Bridge di header bridge. Di Project Navigator klik pada proyek dengan nama objcdan kemudian pilih:

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

Step_07: Seret-dan-lepas Anda Objc-Bridging-Header.hke dalam kotak itu untuk menghasilkan jalur file.

masukkan deskripsi gambar di sini

Step_08: Buka Objc-Bridging-Header.hfile Anda dan impor file Objective-C yang ingin Anda gunakan dalam file Swift Anda.

#import "SpecialObjcFile.m"

Berikut isi dari SpecialObjcFile.m:

#import <Foundation/Foundation.h>

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

Step_09: Sekarang di file Swift Anda, Anda bisa menggunakan kelas Objective-C:

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

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Andy
sumber
1

Logans answer berfungsi dengan baik kecuali yang terbaru Swift 5memberikan beberapa kesalahan kompiler. Ini adalah perbaikan untuk orang-orang yang bekerja pada Swift 5.

Cepat 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
sumber
1

Konsumen cepat, produsen Objective-C

  1. Tambahkan header .hdan .mfile Implementasi - File kelas Kakao (Objective-C)
    MisalnyaMyFileName

  2. mengkonfigurasi bridging header
    Ketika Anda melihat Would you like to configure an Objective-C bridging headerklik - Ya

    • <target_name>-Bridging-Header.h akan dihasilkan secara otomatis
    • Pengaturan Bangun -> Objective-C Bridging Header
  3. Tambahkan Kelas ke Bridging-Header
    Di <target_name>-Bridging-Header.htambahkan baris#import "<MyFileName>.h"

PS Jika Anda harus menambahkan file Objective-C yang ada ke dalam proyek Swift, tambahkan Bridging-Header.hterlebih dahulu

Konsumen Objective-C, produsen Swift

  1. Tambahkan <MyFileName>.swiftdan perpanjangNSObject

  2. Impor File Swift ke ObjC Class
    Tambahkan #import "<#YourProjectName#>-Swift.h"ke file Objective-C Anda

  3. Tandai kode Swift publik [@objc dan @objcMembers]

yoAlex5
sumber
0

Apple telah memberikan panduan resmi dalam dokumen ini: how-to-call-objective-c-code-from swift

Inilah bagian yang relevan:

Untuk mengimpor satu set file Objective-C ke dalam kode Swift dalam target aplikasi yang sama, Anda mengandalkan file header bridging Objective-C untuk mengekspos file tersebut ke Swift . Xcode menawarkan untuk membuat header ini ketika Anda menambahkan file Swift ke aplikasi Objective-C yang ada, atau file Objective-C ke aplikasi Swift yang ada.

Jika Anda menerima, Xcode membuat file header bridging bersama dengan file yang Anda buat, dan menamainya dengan menggunakan nama modul produk Anda diikuti oleh "-Bridging-Header.h". Atau, Anda dapat membuat header penghubung sendiri dengan memilih File> New> File> [sistem operasi]> Sumber> File Header

Edit header penghubung untuk mengekspos kode Objective-C Anda ke kode Swift Anda:

  1. Di header bridging Objective-C Anda, impor setiap header Objective-C yang ingin Anda paparkan ke Swift .
  2. Di Bangun Pengaturan, di Swift Compiler - Pembuatan Kode, pastikan pengaturan membangun Objective-C Bridging Header memiliki jalur ke file header bridging. Path harus relatif terhadap proyek Anda, mirip dengan cara jalur Info.plist Anda ditentukan dalam Pengaturan Bangun. Dalam kebanyakan kasus, Anda tidak perlu mengubah pengaturan ini.

Setiap header Objective-C publik yang tercantum dalam header bridging terlihat oleh Swift.

Tibin Thomas
sumber
0

Pendekatan dua arah untuk menggunakan objektif-c objektif-c

1

  1. Buat file bridge-header.h di Proyek Xcode
  2. impor file .h dalam file bridge-Header
  3. Tetapkan jalur bridge-Header dalam pengaturan Build.
  4. Bersihkan Proyek

2

  1. Buat file obyektif-c dalam proyek (secara otomatis mengatur path di Build Settings untuk Anda)
  2. impor file .h dalam file bridge-Header

Sekarang baik untuk pergi. Terima kasih

Sanjay Mali
sumber