Objective-Cで書いたinstancetypeを返すメソッドがswiftから実行出来ない場合の対処
SwiftとObjective-Cが共存するプロジェクトでAPI呼び出し部分で下記のような問題に直面しました。
Objective-Cで実装されている下記のようなinstancetype型を返すクラスメソッドを
Swiftから呼び出しを行おうとすると、コンパイラエラーが発生しました。
Objective-C interfface
@interface MyBook: NSObject
+ (instancetype)book;
@end
Swift 呼び出し
let mybook = MyBook.book()
'book()' is unavailable: use object construction 'MyBook()'
なぜエラーになるか?
bookメソッドが下記条件を満たしているため、 コンパイラにはconvinience methodとして認識されてしまい、コンパイルエラーを吐いてしまっているようです。
- 引数を取っていない関数である
- クラスの派生的な命名となっている
たとえば、下記のようなクラス名でinterfaceを持つ場合、
@interface LegacySomething: NSObject
+ (instancetype)something;
+ (instancetype)thing;
@end
Swiftで実行すると下記の結果となります。
let mySomething = LegacySomething.something() ## Error
let myThing = LegacySomething.thing() ## Success
解決するには
上記サンプルにもあるように命名を変更するだけで対応することが可能です。
たとえば、UIApplicationで利用されているようなsharedApplicationのような命名は有効で、
コンパイラはこれがconvinienceメソッドだと認識しなくなるようです。
@interface UIApplication: NSObject
+ (instancetype)sharedApplication;
@end
let application = UIApplication.sharedApplication()
今回はinterfaceを拡張して無事Swiftから実行できるようになりました🎉
@interface MyBook: NSObject
+ (instancetype)book;
+ (instancetype)sharedBook;
@end
ref