【问题标题】:How to know which method performed selector in Objective-C如何知道在 Objective-C 中哪个方法执行了选择器
【发布时间】:2023-03-20 22:10:01
【问题描述】:

我有一个非常简单的示例,但我不明白如何获取有关在其中调用选择器的方法的信息。例如:

-(void)methodOne {
   [self performSelector:@selector(methodTwo:)];
}
-(void)methodTwo:(id)sender {
   //How to know which method performed selector???
}

我觉得这个例子很简单,我只需要明白这一点,再次,问题是,我怎么知道从 methodTwo: 哪个方法执行选择器,那么我从哪个方法调用 方法二:。

提前致谢!

【问题讨论】:

    标签: objective-c ios xcode oop selector


    【解决方案1】:

    如果您确实想知道哪个方法调用了您的methodTwo,您可以查看调用堆栈。看看这个……

    -(void)methodOne {
      [self performSelector:@selector(methodTwo:)];
    }
    
    -(void)methodTwo:(id)sender {
      NSLog( @"%@", [NSThread callStackSymbols][1]);
      NSLog( @"%@", [NSThread callStackSymbols][2]);
    }
    

    ...并且日志输出(简化)是...

    0x014ef671 -[NSObject performSelector:] + 62
    0x00002307 -[CMAppDelegate methodOne] + 55
    

    ...callStackSymbols 返回带有调用堆栈符号的NSArray,因此,您可以查看索引 1 以获取您调用方法的方法。如您所见,有NSObjectperformSelector,这是因为您通过performSelector 调用了methodTwo。如果您以这种方式更改您的methodOne ...

    -(void)methodOne {
      [self methodTwo:nil];
    }
    

    ...输出是...

    0x000022fe -[CMAppDelegate methodOne] + 62
    0x000025d6 -[CMAppDelegate application:didFinishLaunchingWithOptions:] + 374
    

    ...就是这样。你的问题得到了回答,但我不知道你为什么想要这个。您可能不想知道究竟是哪个方法调用了您的方法,而是哪个对象启动了这个调用链。一个例子是按钮 - 您可以使用一种方法来处理更多按钮,并且有 sender 参数来区分这些按钮,正如@stavash 指出的那样。

    【讨论】:

    • 在我还在打字的时候,你好像在我之前提到了NSThread的调用堆栈方法! :-p
    【解决方案2】:

    尝试使用 performSelector:withObject:

    -(void)methodOne {
       NSString *identifierStr = @"methodOne";
       [self performSelector:@selector(methodTwo:) withObject:identifierStr];
    }
    -(void)methodTwo:(NSString *)senderIdentifierStr {
       NSLog(@"Sent by %@",senderIdentifierStr);
    }
    

    【讨论】:

    • 您可以使用performSelector:withObject:...afterDelay:0.0 位是多余的。
    • 你说得对,我正在查看 NSObject 文档,它只有“afterDelay:”版本,尽管 NSObject 协议文档也有缩短版本。很奇怪,不是吗?
    • 不,它在文档中。你混合了两件事 - NSObject 类和 NSObject 协议。两者都存在。
    • 我知道它们都存在,只是“performSelector:withObject:”的文档不在 NSObject 文档中。i923.photobucket.com/albums/ad76/stavash/1.png
    • 罗伯特,我知道它在那里,但它不在 STANDARD NSObject 文档中,您需要挖掘才能找到它。这就是我要说的。
    【解决方案3】:

    您无法从第二种方法中知道哪个方法调用了它,至少在不通过调用堆栈的情况下(请参阅NSThread),但您可以从第一种方法中传递此信息,如下所示:

    - (void)doSomething {
        [self doSomethingElseWithCallee: NSStringFromSelector(_cmd) andSender: self];
    }
    
    - (void)doSomethingElseWithCallee: (NSString *)selector andSender: (id)sender] {
        // Do something…
    }
    

    或者您可以直接传递选择器(SEL 类型),而不是字符串:

    - (void)doSomething {
        [self doSomethingElseWithCallee: _cmd andSender: self];
    }
    
    - (void)doSomethingElseWithCallee: (SEL)selector andSender: (id)sender] {
        // Do something…
    }
    

    顺便说一句,_cmd 是 Objective-C 运行时传递给您的方法的特殊参数,以及 self(当前对象)。它们不包含在您的方法签名中,但编译器会为您完成所有工作。 ;-)

    所有人都为 Objective-C 语言欢呼! :-p

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多