質問

ソースを持たないObjective Cクラスのメソッドをオーバーライドしたい。

調査しましたが、カテゴリでこれを行うことができるようですが、古いメソッドの結果を取得するためにsuperを使用して、新しいメソッドで古いメソッドの結果を使用したいと思います。

これを試すたびに、メソッドが呼び出されますが、「super」 nil ...理由は何ですか? XCode 2.2 SDKを使用してiPhone開発を行っています。私は間違いなくクラスのインスタンスで作業しており、クラスのメソッドはインスタンスメソッドです。

@implementation SampleClass (filePathResolver)
-(NSString*) fullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [super fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

注意と説明:Apple Docsで見ることができるものから、これは許可されるべきだと思われますか?

  

developer.apple.comのカテゴリドキュメント:   カテゴリが継承されたメソッドをオーバーライドする場合、   カテゴリは、通常どおり、   メッセージを介した継承された実装   スーパーに。ただし、カテゴリ   既にメソッドをオーバーライドします   カテゴリーのクラスに存在していた   オリジナルを呼び出す方法はありません   実装。

役に立ちましたか?

解決

カテゴリは元のクラスを拡張しますが、サブクラスは作成しません。したがって、 super を呼び出してもメソッドは見つかりません。

必要なものは Method Swizzling と呼ばれます。ただし、コードが何かを壊す可能性があることに注意してください。古いObjective-Cランタイムでのメソッドスウィズリングについて、 Scot Stevensonによって書かれたTheocacao に関する記事があります。 Matt Gallagherの愛を込めたCocoa には、新しいObjectiveのMethod Swizzlingに関する記事があります。 -C 2.0ランタイムとその単純な置き換え。

別の方法として、クラスをサブクラス化してからサブクラスを使用するか、 +(void)poseAsClass:(Class)aClass でスーパークラスを置き換えます。 Appleの書き込み:

  

ポーズクラスによって定義されたメソッド    super へのメッセージを通じて、   スーパークラスメソッドを組み込む   オーバーライドします。

AppleはMac OS X 10.5で poseAsClass:を廃止していることに注意してください。

他のヒント

このクラスに対してコーディングする場合は、セレクターをコードで使用できる名前に変更し、 self で元のセレクターを呼び出します。

@implementation SampleClass (filePathResolver)
-(NSString*) myFullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [self fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

そのクラスのこのセレクターのデフォルトの実装をオーバーライドする場合は、スウィズリングメソッドアプローチ。

正確にはカテゴリに含まれていませんが、実行時にメソッドを動的に追加することで回避策があります。 Samuel Dé fagoは彼の記事で、スーパーを呼び出すブロックIMP実装を作成するきちんとした方法について説明しています。彼の元の記事はここ

関連するコードは次のとおりです:

#import <objc/runtime.h>
#import <objc/message.h>

    const char *types = method_getTypeEncoding(class_getInstanceMethod(clazz, selector));
    class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) {
        struct objc_super super = {
            .receiver = self,
            .super_class = class_getSuperclass(clazz)
        };

        id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
        return objc_msgSendSuper_typed(&super, selector, argp);
    }), types);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top