2015-09-21 9 views
10

混合フレームワークでの作業。 Obj-Cファイルの中にインポートされますが、内部クラスは公開されていません。同じフレームワーク内でObjective-Cの内部Swiftクラスにアクセスする方法は?

ドキュメントは明らかに内部claseesはスウィフトとのObj-Cの間で利用可能であるべき状態:

があなたと同じフレームワークをターゲットにスウィフトファイルのセットをインポートするにはObjective-Cの
にスウィフトのインポートObjective-Cコードでは、 は、フレームワークの傘のヘッダーに何かをインポートする必要はありません。 代わりにSwiftコード のXcode生成ヘッダーファイルを、Swiftコードを使用するObjective-C .mファイルにインポートします。 フレームワークターゲットの生成されたヘッダーは フレームワークのパブリックインターフェイスの一部であるため、パブリック 修飾子が付いた宣言のみが、フレームワークターゲットの生成されたヘッダーに表示されます。 あなた はまだスウィフト方法と、あなたのフレームワークのObjective-Cの部分の中から 内部修飾子でマークされたプロパティを使用することができ、 は限りが Objective-Cのクラスから継承したクラス内で宣言されている 。アクセスレベル修飾子の詳細については、 Access ControlThe Swift Programming Language (Swift 2)に記載しています。ドキュメントに示されているように

コードサンプル(フレームワークを使用して新しいプロジェクトを作成します)

// SwiftObject.swift 

public class SwiftObject: NSObject { 
    public class func doSomething() {} 
} 

internal class YetAnotherSwiftObject: NSObject { 
    internal class func doSomething() {} 
} 

// SomeObject.m file 

@implementation SomeObject 

- (void)someMethod { 
    [SwiftObject doSomething]; 
} 

- (void)someOtherMethod { 
    [YetAnotherSwiftObject doSomething]; // Use of undeclared identifier 
} 

@end 

答えて

16

internal修飾子でマークされた宣言は、生成には表示されません。コンパイラはそれらのことを知らず、したがって苦情を受け取りません。もちろん、performSelectorアプローチを使用してメッセージを送信することもできますが、それは便利でバグが発生しにくいものです。これらの宣言がそこにあることをコンパイラに知らせるだけです。

まず、我々はあなたがObjective-Cであなたのシンボルの名前を指定することができます@objc属性バリアントを使用する必要があります。

// SwiftObject.swift 

@objc(SWIFTYetAnotherSwiftObject) 
internal class YetAnotherSwiftObject: NSObject { 
    internal class func doSomething() {} 
} 

そして、あなたはちょうどあなたが使用したい方法で@interface宣言を作成する必要がありますあなたのコードで - そうコンパイラが幸せになる、ともあなたは以前指定したシンボル名を持つSWIFT_CLASSマクロを適用します - ので、リンカは実際の実装を選ぶだろう:

// SomeObject.m file 

SWIFT_CLASS("SWIFTYetAnotherSwiftObject") 
@interface YetAnotherSwiftObject : NSObject 

+ (void)doSomething; 

@end 


@implementation SomeObject 

- (void)someOtherMethod { 
    [YetAnotherSwiftObject doSomething]; // Should work now !!! 
} 

@end 
  • わかりやすくするために.mファイルのインタフェース宣言を使用しましたが、そのような宣言を.hファイルに組み込んでインクルードする方が良いでしょう。
  • このインタフェースでメソッドを宣言することで、コンパイラに対する約束をしています。存在しないメソッドを置くと文句を言うことはありません。その場合は実行時にクラッシュするので、慎重にしてください。
+0

ニース!私はそのマクロについて知らなかったし、Googleはあまり表示していない。 Appleのドキュメントから参考になっていますか? – Yariv

+4

いいですか?これはひどく冗長で乱雑です。これは本当にあなたがする必要がありますか?私は同じ問題に遭遇しており、リンゴさえもこれ以上のことをする必要がありました。私はこれをあきらめて、客観的なCに戻るつもりです、これは不合理です!実際に動作するもの(検索時間後)を投稿する場合は+1してください。 –

+3

Appleのドキュメントによれば、「Objective-Cクラスから継承するクラス内で宣言されている限り、フレームワークのObjective-C部分から内部修飾子でマークされたSwiftメソッドとプロパティは引き続き使用できます。 swiftクラスが別のobjcクラスから派生している場合、objcコードで利用できるはずです。私は同様の問題を抱えていて、@ objcを使用して素早くクラスをマークし、NSObjectから継承しましたが、objcコードではまだ使用できません。 – puru020

3

私の場合は、「アプリ拡張APIのみ許可」を確認していました。プロジェクト設定に移動してターゲットを選択すると、[展開情報]の[全般]タブに表示されます。

誰かが私にこの問題を解決する理由を説明することはできますか?

+0

私はあなたを愛しています!笑 。この愚かな制限を回避する答えを見つけたのは、地球上の唯一の場所です。内部ObjCコードと相互に作用できるように、SwiftクラスをAPIコンシューマに公開するためのフレームワークは必要ありません。 – nobre

+0

このオプションを使用するように注意してください!自動生成されたヘッダーのクラスとメソッドをリストします。それらを非公開にする気にしない場合にのみ使用してください。 – Amit

+0

これをチェックすると、たくさんのCocoa APIが見つからなくなります。 – Martin

関連する問題