Objective-C sınıfında bir Swift protokolünü içe aktarma


116

Adlı AnalyticProtocolbir Objective-C sınıfı olarak adlandırılan bir Swift Protokolünü içe aktarmaya çalışıyorum AnalyticFactory.

protocol AnalyticProtocol
{

}

Mevcut bir Objective-C projesinden başlıyorum (xCode ile yeni bir Swift projesi oluşturmadım ve Objective-C projemi xCode 6'da Swift projesi olacak şekilde nasıl yapılandırılacağını bulamadım ).

Swift dosyama .hadlı dosyayı ekledim MyProjectName-Swift.hancak derleyici bana bunun olmadığını söyleyen bir hata verdi . Bu yüzden, aslında boş olan bir .hdosya oluşturdum MyProjectName-Swift.h(içine ne koymam gerektiğini bilmiyorum).

In Apple belgelerine onlar benim eklemek zorunda olduğunu söyledi .hadlı dosyayı MyProjectName-Swift.hbenim de .mdosyaya. Ama bunu dosyama değil dosyama .meklemem gerekiyor.h . Bu sorunlu olabilir mi?

Derlemeye çalıştığımda şu hatayı alıyorum:: 0: hata: xxxAnalyticFactory.h: 39: 'AnalyticProtocol' için protokol bildirimi bulamıyorum

Ve suçlu kodu:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Bir Swift protokolünü bir Objective-C sınıfına nasıl aktarabileceğimi iyi anlamadığımı düşünüyorum.

Yaptığım şeyde hata gören var mı?


Check out entegre Swift Objective-C ile etrafında 30:40 video içine At WWDC 2014 videonun, onlar erişimine nasıl Objective-C sınıflarında Swift protokolleri açıklar.
Jamie Forrest

Yanıtlar:


224

@objcÖzniteliği Swift protokolünüze şu şekilde eklemeniz gerekir :

@objc protocol AnalyticProtocol {

}

25
Cevabınız için teşekkürler ama sorun hala devam ediyor.
Jean Lebrument

Sorunu yeniden üreten örnek bir proje yayınlayabilir misiniz?
Jamie Forrest

@Objc'yi eklemek Swift derslerini Obj-C'ye aktarmama yardımcı oldu
serg

19
@objc her zaman çalışmaz. Bir protokole uygun zaman konulu protokolü eklerken bazen çalışmıyor @interfaceiçinde .hdosyanın. ancak, özel protokolü ekleyebilir @interfaceiçinde .mdosyanın ve (en azından zaman zaman benim için vardır) şeyleri düzeltir. Yani yukarıda senin @implementationvar @interface MyController() <AnalyticProtocol>.
Adam

1
Bazen düzenleme sırasında Xcode 8 şikayet edebilir, ancak gerçekten oluşturduğunuzda, bu yanıtı yorumlarla birlikte takip ederek hata ortadan kalkacaktır.
Roger Pingleton

77

Xcode tarafından üretilen Swift başlığını objC başlık dosyalarına aktarmak mümkün değildir.

Dolayısıyla, bir objC başlık dosyasında Swift kodunu kullanmak istediğinizden, objC başlık dosyasında kullanmak istediğiniz sınıfları ve protokolleri şu şekilde "ileri bildirmeniz" gerekecektir:

@protocol AnalyticProtocol;

Artık protokolü objC sınıf bildiriminizde kullanabilirsiniz:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Uygulama dosyanızda (objC .m dosyası), Xcode tarafından oluşturulan Swift üstbilgisini ("ProductModuleName-Swift.h") içe aktarabilirsiniz ve doğru uygulama AnalyticProtocolartık derleyici tarafından bilinecektir.

Bu aynı zamanda Apple Dokümanlar'daki "Objective-C'den Swift Kullanımı" bölümünde de açıklanmaktadır.

İleriye dönük bildirilen protokolü kullandığınızda XCode'un objC başlık dosyasında bir uyarı vereceğini unutmayın ("'AnalyticProtocol' için protokol tanımı bulunamıyor '), ancak bu göz ardı edilebilir - uygulama derleme zamanında bulunacaktır.


19
Xcode, derlerken ve düzgün çalışıyorken neden eksik protokol uyarısını gösteriyor? Uyarıyı kaldırmanın bir yolu var mı?
Ören

Yine de bu sınıfta protokol yöntemlerini çağırmak mümkün değildir. Bu hata verecektirNo visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa

aşağıdaki uyarıyı verir: "xxxx için protokol tanımı bulunamıyor"
JAHelia

51

Sadece bir protokolü benimsemeye ihtiyaç duyan herkes için - bunu herhangi bir uyarı veya hata oluşturmadan iki adımda yapabilirsiniz:

  1. Senin içinde .swiftdosyaya eklemek @objcprotokol adından önce:

    @objc protocol AnalyticProtocol {
    
    }
  2. Senin içinde .mdosyanın, üretilen Swift başlığını ithal ve özel kategoride protokolü benimsemesi. (Başlık dosyası otomatik olarak adlandırılır):

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end

Bu, Apple'ın önerdiği yaklaşımdır. Objective-C ve Swift'i karıştırma ve eşleştirme hakkında daha fazla bilgiyi buradan edinebilirsiniz: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html


1
İleriye dönük beyanla veya olmadan hala bir uyarı alıyorum. Protokolü bir uzantıda kullanıyorum.
Cristi Băluță

İçe aktarılamıyor #import "AnalyticProtocol-Swift.h". Görünüşe göre WhateverProtocol-Swift.h, söylediğiniz gibi otomatik olarak oluşturulmamış.
Hlung

2
Bu benim için çalıştı; bu sayfadaki başka öneri veya yanıt işe yaramadı. Ben Swift
Poulsbo

1
Bu, uyarıyı kaldırmanın tek yoluydu (protokoller başlık dosyasındayken çalışsa bile)
David P


3

Bir çerçeve oluşturuyorsanız, gerekli içe aktarma

#import "ProductModuleName-Swift.h"

şu şekilde değişir:

#import <ProductModuleName/ProductModuleName-Swift.h>

Bu durumda, swift protokolünü de herkese açık hale getirmelisiniz :

@objc public protocol AnalyticProtocol {
  func something();
}

3

Kodda birkaç değişiklik yaparak Objective C'de hızlı protokolleri kullanabiliriz. Ayrıca @objc tarafından bildirilen protokoller, varsayılan uygulamalar olmadan isteğe bağlı ve gerekli yöntemlere sahip olmanıza izin verir. Artıları ve eksileri ile birlikte gelir.

Aslında, Objective C'de kullanırken protokol adını daha açıklayıcı bir şekilde yeniden adlandırabiliriz. "@Objc (alias_name)" kullanıyorum.

İşte kod, ObjC kodunda kullanmak için @objc özniteliği ve takma ad ile hızlı bir protokol yapalım.

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

Şimdi farword protokolümüzü .h dosyasında bildirelim

@protocol ObjTableViewReloadable;

Artık bu protokole .m dosyasında uyabilir ve gerekli yöntem uygulamasını ekleyebilirsiniz.

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

Bunu gönderdiğiniz için teşekkürler. Kirden daha eski olan eski koda bakıyorum ve bu yaklaşım işe yararsa, beni bir ton acıdan kurtaracak. :)
Adrian
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.