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.