Object-c kodu, Class'ta swift uzantısını çağırabilir mi?


99

Bazı gönderileri araştırdım, sanırım hızlı bir uzantı yazıp Objective-C kodundan arayamam, değil mi?

@objc gibi öznitelikler yalnızca yöntemleri, sınıfı, protokolleri destekliyor mu?


1
Neden bir denemiyorsun?
HAS

7
ide hatadan şikayet etti, ancak kesin bir yanıt almak istiyorum.
sprhawk

Yanıtlar:


88

Bir Swift eklentisi yazıp bunu Objective-C kodunda kullanabilirsiniz. XCode 6.1.1 ile test edilmiştir.

Yapmanız gereken tek şey:

  • uzantınızı Swift'de oluşturun ( @objcaçıklama yok )

  • #import "ProjectTarget-Swift.h" Objective-C sınıfınızda (burada "ProjectTarget", Swift uzantısının ilişkilendirildiği XCode hedefini temsil eder)

  • Swift uzantısından yöntemleri çağırın

Güncelleme: @Rizwan Ahmed'in bahsettiği gibi, @objcek açıklama eklemeniz gerekiyor :

Swift 4.0.3'ten itibaren, uzantıyı Objective C sınıfı dosyalarında kullanmak istiyorsanız @objc ek açıklaması gereklidir.


6
Bunu tam olarak yaptım ama yine de bir derleme zamanı hatası. Hmmm. DÜZENLEME: "ProjectTarget-Swift.h" yerine köprü başlığımı içe aktardım. Der.
Jason Renaldo

Her ikisi de köprüleme başlıklarıdır. Aradaki fark, biri ObjC'de Swift kodunu kullanmak, diğeri ise Swift'de ObjC kodunu kullanmak içindir. Swift başlığı görünmez. Diğeri, sizin tarafınızdan yönetilmelidir.
marius bardan

William Hu, mclaughlinj'in cevabına bakın!
appleitung

39
Swift 4.0.3'ten itibaren, uzantıyı Objective C sınıfı dosyalarında kullanmak istiyorsanız @objc ek açıklaması gereklidir.
Rizwan Ahmed

NOT: Proje hedefinizin adı içinde bir tire işareti içeriyorsa, bu kısa çizginin import ifadesinden kaldırılması gerekir. Örneğin, proje hedefinizin adı "proje hedefi" ise, bu durumda import deyimi "projecttarget-Swift.h" yazmalıdır.
Tyler Ahşap

70

Ben de öğrendim Swift 4.0 ben eklemek zorunda @objcbenim önünde uzatma ı uzatılacağı objc sınıfının bir örneği tarafından görünür hale Swift uzatma yöntemleri için sırayla anahtar kelime.

Kısacası:

Dosya yapılandırma kurulumu:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

CustomClassExtension'da:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

AppDelegate.m'de:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];

2
Bir yöntem jenerik kullanıyorsa, Objective-C tarafından kullanılamaz ve @nonobjcek açıklamayı eklemeniz gerekir .
ThomasW

Sadece bir yan not, @objcMembers bu durumda çalışmaz. Neden bilmiyorum .. :-(
Raunak

48

Bu çözüm Swift 2.2 ve Swift 3 için çalışıyor . Objective-C'den yalnızca sınıflar için uzantılara (yapılar veya numaralandırmalar için değil) erişilebileceğini unutmayın.

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Sonra ObjC dosyanıza #import "ProductModuleName-Swift.h" yazın.

Swift 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

"ProjenizinAdı Burada ..." değil, "HedefinizAdı Burada ...": hedefleri paylaşmak için kilitlemeniz gerekir: dr2050.postach.io/post/…
Dan Rosenstark

1
@DanRosenstark Doğru söylüyorsunuz. Apple'ın önerdiği gibi "ProductModuleName-Swift.h" olarak değiştiriyorum: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim

1
Hızlı 3 için iyi çalışıyor
Viktor Kucera

publicGerekli olduğunu söylemenizin bir nedeni var mı ? publicBenim için değiştirici olmadan iyi çalışıyor . Uzantının aynı projede olmadığını, ancak başka bir projeden ithal edildiğini mi varsayıyoruz?
Lee Kang

Köprüleme başlığı kullanmam gerekir mi?
jegadeesh

42

Diğer yanıtlarda ele alındığı gibi, oluşturulan Swift başlığını içe aktarmak çoğu durumda işe yarar .

Bunun bir istisnası, kategorinin köprülü bir tipte tanımlanmasıdır (yani uzantı üzerinde tanımlanır Stringve tanımlanmaz NSString). Bu kategoriler otomatik olarak Objective-C meslektaşlarına köprülenmeyecek. Bunu aşmak için, ya Objective-C türünü kullanmanız (ve dönüş değerini Swift kodunuzda atmanız as String) ya da hem Swift hem de Objective-C türleri için bir uzantı tanımlamanız gerekir.


2
Yukarıdaki cevaba ek olarak, hızlı uzantınızı genel yapmalı ve türünü NSString olarak belirlemelisiniz örn public extension NSString. Derleme zamanında çözülmemiş bir tanımlayıcı veya benzer bir hata alırsanız, örneğin let sVal = self as StringsVal
String'e

@RunLoop aslında herkese ihtiyacınız yok, kapsam belirticisi olmadan çalışacaktır. Ve (Obj-C'ye dışa aktar, demek istediğim) Dizeler için işe yaramaz, çünkü bunlar sınıflar değil yapılardır ve yalnızca Swift'den alınabilir. Yani, evet - NSString için uzantı yazabilir ve mclaughlinjhem NSString sınıfı hem de String yapı için söylendiği gibi cast kullanabilir veya uzantılar yazabilirsiniz
Alex Nazarsky

3

İthalat "#import 'ProductModuleName-Swift.h' nesnel-c dosyasındaki başlık ve eklemek @objc sizin Infront de gerçekten hızlı dosyasında. O Swift 4.2 ve swift 5'de iyi çalışıyor olacak


0

Her şeyi doğru bir şekilde yapılandırdığınızı düşünüyorsanız (Swift varlıklarınızı @objcMembers veya @objc ile işaretleyin, köprüleme başlığını "ProductModuleName-Swift.h" vb. İçe aktarın) - ancak yine de No visible @interface for 'FooClass' declares the selector 'fooSelector'hatayı alıyorsanız :

Eğer köprü başlığında arayüzleri görürseniz kontrol tarafından ctrl + cmdüzerine tıklayarak. Eğer yoksa, bu soruya verdiğim cevaba bir göz atın : Swift to Objective-C başlığı Swift sınıfları içermiyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.