Kapan menggunakan @objc di Swift?


89

Di Swift, saya melihat beberapa metode seperti:

@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)

Saya bertanya-tanya, kapan harus menggunakan @objc? Saya membaca beberapa dokumen, tetapi mereka mengatakan ketika Anda ingin itu dapat dipanggil di Objective-C, Anda harus menambahkan bendera @objc

Namun, ini adalah fungsi pribadi di Swift, apa yang dilakukan @obj?


1
pertanyaan yang bagus !!!
Erhan Demirci

Jawaban:


68

private berarti hanya terlihat di Swift. jadi gunakan @objc agar terlihat di Objective-C. Jika Anda memiliki func to selector, sebuah fungsi privat dengan cepat, itu diperlukan.

Atribut @objc membuat Swift API Anda tersedia di Objective-C dan runtime Objective-C.

Lihat: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html


1
Jadi @objc private func doubleTapGestureRecognized, apa gunanya memiliki @objc dan pribadi? Apakah Anda mengatakan kelas Objective-C bisa menimpa doubleTapGestureRecognized?
Wingzero

1
Saya kira, karena dalam obj-c Anda dapat menimpa metode apapun juga.
strangetimes

2
Tidak yakin bagaimana jawaban ini benar & menjawab Q-nya. Jawaban yang diberikan di sini sudah ada di Q-nya sendiri "tetapi mereka mengatakan ketika Anda ingin memanggilnya di Objective-C, Anda harus menambahkan \ @objc flag", utamanya T adalah "Ini adalah fungsi pribadi dengan cepat, apa yang dilakukan \ @obj?"
KBJ

3
Tautan putus. Terutama ke dalam dokumentasi Apple. Harap pertimbangkan untuk mengekstrak elemen kunci dari dokumentasi di sini.
levigroker

57

Jawaban terlambat lainnya, tetapi tidak ada jawaban yang ada pada pertanyaan ini yang benar-benar menjawab pertanyaan OP, yaitu: mengapa sih yang perlu Anda gunakan @objcpada anggota privatekelas, jika @objcada untuk interaksi dengan Objective-C, dan anggota yang bersangkutan bersifat pribadi, artinya meskipun Anda memiliki kode Objective-C dalam proyek Anda, ia seharusnya tidak dapat melihat anggotanya?

Alasannya adalah, karena banyak framework yang ditulis di Objective-C, terkadang fitur Objective-C diperlukan untuk berinteraksi dengan API tertentu.

Misalnya, saya ingin mendaftar notifikasi melalui DistributedNotificationCenter:

DistributedNotificationCenter.default.addObserver(self,
                                                  selector: #selector(somethingHappened(_:)),
                                                  name: someNotification,
                                                  object: nil)

Agar ini berfungsi, kita harus bisa mendapatkan pemilih untuk somethingHappenedmetode tersebut. Namun, penyeleksi adalah konsep Objective-C, jadi jika metode tidak terlihat oleh Objective-C, itu tidak memiliki selector. Oleh karena itu, meskipun metode tersebut bersifat pribadi dan tidak boleh dipanggil oleh kode luar arbitrer, ia memerlukan @objcagar DistributedNotificationkode, yang ditulis dalam Objective-C, dapat memanggilnya melalui selektornya.

Kasus umum lainnya @objcyang diperlukan adalah untuk mendukung Key-Value Coding (KVC), terutama di macOS, di mana KVC dan KVO digunakan untuk mengimplementasikan Cocoa Bindings. KVC, seperti banyak sistem lain di Cocoa, diimplementasikan di Objective-C, yang memiliki efek mengharuskan properti yang sesuai dengan KVC diekspos ke runtime Objective-C. Terkadang, masuk akal jika properti yang sesuai dengan KVC bersifat pribadi. Salah satu contohnya adalah ketika Anda memiliki properti yang memengaruhi properti lain:

@objc private dynamic var originalProperty: String

@objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [
    #keyPath(originalProperty)
]
@objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }

Dalam hal ini, milik kita yang sebenarnya disimpan pribadi, tetapi milik tergantung, yang kita lakukan mengekspos kode luar, perlu mengirim pemberitahuan ketika properti pribadi diperbarui. Dengan menandai properti pribadi sebagai @objc, kita dapat dengan mudah melakukannya dengan menyiapkan ketergantungan KVC — jika tidak, kita harus menulis kode untuk mengirim pemberitahuan secara manual di properti willSetdan didSetpenangan pribadi. Selain itu, properti statis yang menginformasikan sistem KVC yang dependentPropertybergantung pada originalPropertyperlu diekspos ke Objective-C sehingga sistem KVC menemukan dan memanggilnya, tetapi itu tidak relevan untuk klien kode kami.

Selain itu, pengontrol tampilan di app macOS yang memperbarui kontrol dalam tampilannya menggunakan Cocoa Bindings sebagai detail implementasi dapat membuat properti pribadi tertentu sesuai dengan KVC untuk mengikat kontrol tersebut ke properti tersebut.

Jadi seperti yang Anda lihat, ada kalanya metode atau properti perlu diekspos ke Objective-C untuk berinteraksi dengan kerangka kerja, tanpa harus terlihat oleh klien kode Anda.


Terima kasih. Ini adalah jawaban bagus yang menjawab pertanyaan secara langsung.
HQt

25

@objc / dinamis

Ini untuk kompatibilitas: Setelah Anda mengimpor file / kode Swift Anda ke dalam proyek berbasis Objective-C.

Dan gunakan itu jika Anda ingin properti / metode Anda diakses oleh kode atau kelas Objective-C.

Sebagian besar waktu itu terjadi ketika Anda mengelompokkan kelas Swift dari kelas dasar Objective-C.

Kelas atau protokol Swift harus ditandai dengan atribut @objc agar dapat diakses dan digunakan di Objective-C. Atribut ini memberi tahu kompiler bahwa potongan kode Swift ini dapat diakses dari Objective-C. Jika kelas Swift Anda adalah turunan dari kelas Objective-C, kompilator otomatis menambahkan atribut @objc untuk Anda.

Berikut dokumentasi apel yang mengatakan tentang @objc.

Menggunakan Swift dari Objective-C

Kompatibilitas Interoperabilitas Bahasa

Tautan Diperbarui:
Sepertinya tautan telah diperbarui oleh apple.


11

@objc adalah atribut kelas, jadi Anda menggunakan

@objc public class MyClass

Ini mengekspos metode kelas ke kelas Objective C, jadi Anda hanya akan menggunakannya jika kelas Anda berisi fungsi publik


8

Jawaban terlambat, tetapi @objcperilaku ini sedikit berubah pada Swift 4 (yang keluar di Xcode 9, yang umumnya dirilis 10 hari yang lalu).

Di Swift 4, beberapa kasus inferensi @objcdihapus. Ini hanya berarti dalam beberapa kasus tambahan di mana sebelum @objcheader disimpulkan oleh kompiler Swift, di Swift 4 tidak disimpulkan.

Baca lebih lanjut di proposal evolusi Swift tentang perubahan ini

Seperti yang telah disebutkan, secara umum @objcadalah mengekspos metode tertentu ke runtime Objective-C, yang merupakan bagian dari interoperabilitas Swift bahasa.


1
jadi ini harus menjadi alasan mengapa setelah memperbarui ke Swift 4 beberapa variabel tidak dapat diakses dari ObjC kan? Dengan Swift 3.X tidak perlu menambahkan@objc
rgkobashi

oh ok, selalu baik untuk mengecek ulang dengan orang lain, terima kasih!
rgkobashi

1

@objcmengekspos deklarasi ke Objective-C runtime. Mari kita lihat #selectorfitur Swift untuk menggunakan runtime Objective-C. Dalam hal ini Anda dapat menentukan Swift Anda @objc private func[Lainnya]

Untuk menggunakan fungsi Swift dari Objective-C:

  1. Kelas Swift harus diperpanjang dari NSObject
  2. Mark Swift:

    Sebuah. hanya @objcMembers kelas - untuk mengekspos semua public konstruktor , bidang , dan metode . Juga berlaku untuk subclass

    b. @objc class / enum / protocol (kecuali struct ) [Named Type]

    • @objc class (opsional) - untuk menampilkan default public init() . Atau @objc(<custom_name>)untuk menyiapkan nama khusus untuk kelas.
    • @objc konstruktor , bidang dan metode - untuk mengeksposnya secara selektif

Metode Swift akan tersedia dengan penamaan berikutnya:

<swiftName>With<firstArgument>:<secondArgument>:

Sebagai contoh:

public func printHelloWorld(arg1: String, arg2:String)
//is reached through: 
[someObject printHelloWorldWithArg1: arg2:];

[ @objcdan dynamic]

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.