まず始めに
Method Swizzlingを行う場合などに、Objective-CではNSObjectのsubclassで +(void)load や +(void)initialize を利用していたかと思います。
しかしながらそれらのクラスメソッドは、SwiftからOverrideしようとすると下記のようなエラーになってしまいます。
Swiftで扱えるようにするには
まずはObjective-Cで定義をします。Swiftで利用する際にextension内でoverrideをして使う形にするため
- _RuntimeHandler (Overrideするためのクラス)
- RuntimeHandler (_RuntimeHandlerを継承し、実際にSwiftで利用するクラス)
を定義します。
RuntimeHandler.h
@interface _RuntimeHandler: NSObject
+ (void)handleLoad;
+ (void)handleInitialize;
@end
@interface RuntimeHandler : _RuntimeHandler
@end
実装ファイル側では
- _RuntimeHandlerにハンドリング用のクラスメッソドを実装
-
RuntimeHandlerでは
+(void)load
と+(void)initialize
を実装し、_RuntimeHandler
に実装したメソッドを呼び出す
という実装をします。
RuntimeHandler.m
#import "RuntimeHandler.h"
@implementation _RuntimeHandler
+ (void)handleLoad {
NSLog(@"Please override RuntimeHandler.handleLoad if you want to use");
}
+ (void)handleInitialize {
NSLog(@"Please override RuntimeHandler.handleInitialize if you want to use");
}
@end
@implementation RuntimeHandler
+ (void)initialize {
[super initialize];
[self handleInitialize];
}
+ (void)load {
[super load];
[self handleLoad];
}
@end
実際に利用する
下記のような形で、Swiftから利用できるようになります。
extension RuntimeHandler {
open override class func handleLoad() {
print("did call handleLoad!")
}
open override class func handleInitialize() {
print("did call handleInitialize!")
}
}
ちなみに
下記のように、Swift側でRuntimeHandlerを継承したクラスを実装したとしても、継承している_RuntimeHandlerの +(void)load
と +(void)initialize
が呼ばれないため、 handleLoad
とhandleInitialize
も呼ばれません。
class Hoge: RuntimeHandler {
open override class func handleLoad() {
print("did call handleLoad!")
}
open override class func handleInitialize() {
print("did call handleInitialize!")
}
}