0

次のコードは例外をスローします。

vcClassClassオブジェクトです ( からの継承者UIViewController)。私の実装Self含まれていますviewWillAppear:

SEL viewWillAppearSEL = @selector(viewWillAppear:);
IMP viewWillAppearWithSuperIMP = [self methodForSelector:viewWillAppearSEL];
class_addMethod(vcClass, viewWillAppearSEL, viewWillAppearWithSuperIMP, @encode(BOOL));
NSMethodSignature *methodSignature = [vcClass instanceMethodSignatureForSelector:viewWillAppearSEL];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setSelector:viewWillAppearSEL];

メッセージ付き:

キャッチされていない例外 'NSInvalidArgumentException' が原因でアプリを終了しています。理由: '-[NSInvocation setArgument:atIndex:]: インデックス (1) が範囲外 [-1, -1]

追加情報: iOS5、ARC。 誰かが私に何が悪いのか説明できますか?

更新しました:

このコードコードは、応答メッセージを表示します。私のクラスオブジェクトは正しい [vcClass instancesRespondToSelector:viewWillAppearSEL] ですか? NSLog(@"応答する") : NSLog(@"応答しない");

また、直後にクラッシュし[invocation setSelector:viewWillAppearSEL];ます。そのため、トピック タイトルをUnexpected exception with NSInvocationと呼びました。

UPDATED2:

また、私の実装viewWillAppear:

- (void)viewWillAppear:(BOOL)animated {
    Class parentViewController = [self superclass];
    void (*superViewWillAppear)(id, SEL, BOOL) =(void(*)(id, SEL, BOOL))class_getMethodImplementation(parentViewController, _cmd);
    superViewWillAppear(self, _cmd, animated);
    NSLog(@"view will appear with super");
}
4

2 に答える 2

1

コードの問題の 1 つは、 に渡す型エンコーディングですclass_addMethod()。この型エンコーディングには、1) 戻り値の型、2)selfおよび_cmd(最初の 2 つの非表示パラメーター) の型、3) 他のすべてのパラメーターの型が含まれている必要があります。

のようなメソッドの場合- (void)viewWillAppear:(BOOL)animated、型エンコーディングは文字列にする必要があります

v@:c

  • v-- for void、戻り値の型
  • @-- for id、タイプ forself
  • :-- for SEL、タイプ for_cmd
  • c-- に対してchar、これはBOOLです。これはあなたがしたときに得られるものです@encode(BOOL)
于 2013-05-18T09:45:59.657 に答える
1

BOOL *arg1;

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setSelector:viewWillAppearSEL];
[invocation setArgument:&arg1 atIndex:2];   // argument indexing is offset by 2 hidden args
于 2013-05-10T12:43:10.313 に答える