Swift で定義したクラスを Objective-C で利用する : Objective-C プログラミング

PROGRAM


Swift で定義したクラスを Objective-C で利用する

Objective-C と Swift とでは、それぞれで定義したクラスを簡単に相互利用できるようになっています。

ここでは Swift で定義したクラスを Objective-C で利用する方法を紹介します。Objective-C で定義したクラスを Swift で使用する方法については Objective-C で定義したクラスを Swift で利用する で紹介します。

Swift クラスが定義されたヘッダーファイルをインポートする

Swift で定義したクラスを利用するには、それを使用したい実装ファイル内に、次のように #import 文を記載します。このとき、下記の $(PROJECT_NAME) のところは、目的の Swift コードが実装されているプロジェクト名に置き換えてください。

#import "$(PROJECT_NAME)-Swift.h"

このファイルは、プロジェクト自体には登録されていないのですが、Derived Data の中間ファイルとして "DerivedSources" フォルダーに自動的に生成されます。

Swift クラスを使用する

たとえば、次のような Swift クラスが定義されていたとします。クラスは NSObject かそれを含むクラスから継承させたものにします。

class EzSwiftObject : NSObject

{

var name: String

var note: String!

 

init(name: String, note: String!)

{

self.name = name

self.note = note

 

super.init()

}

 

convenience init(name: String)

{

self.init(name: name, note: nil)

}

}

このようなとき、Objective-C のソースコードで先ほどの "$(PROJECT_NAME)-Swift.h" ヘッダーさえインポートすれば、次のようにして、この Swift クラスを利用できるようになります。

// 特別な実装をしなくても Objective-C の流儀でインスタンスを生成できます。

EzSwiftObject *obj = [[EzSwiftObject alloc] initWithName:@"OBJ" note:@"SWIFT"];

 

// 生成したインスタンスは Objective-C と変わらない方法で利用できます。

NSLog(@"%@", obj.name);

Swift であれば [[Class alloc] init] のような初期化方法は使いませんし、メソッドも "init(name: note:) のように定義されているのですが、その辺りを Objective-C の構文に適するように自動で調整してくれます。そのため、Objective-C のコードの中では "initWithName:note:" という Objective-C らしい構文を使って Swift クラスを利用できます。

Swift クラスを継承した Objective-C クラスを作ろうとした場合

Objective-C にインポートした Swift クラスを基底クラスにして Objective-C で新たに派生クラスを作成しようとすると、次のようなエラーになります。

Cannot subclass a class with objc_subclassing_restricted attribute

これは、自動的に生成された "$(PROJECT_NAME)-Swift.h" ファイル内の Swift クラスに "SWIFT_CLASS" マクロが添えられていて、その中で "__attribute__((objc_subclassing_restricted))" 属性が使用されているための様子です。

この属性はプリプロセッサマクロで定義されているため、自動生成されたヘッダーを書き換えることなく無理やり外すこともできますが、何を予防する目的で、どこで付けられているかが分からないため、とりあえず Swift クラスは Objective-C クラスでは継承できないと思っておいて良いかもしれません。

[ もどる ]