【问题标题】:when to use respondsToSelector in objective-c何时在 Objective-C 中使用 respondsToSelector
【发布时间】:2010-09-12 23:17:31
【问题描述】:
- (void)someMethod
{
    if ( [delegate respondsToSelector:@selector(operationShouldProceed)] )
    {
        if ( [delegate operationShouldProceed] )
        {
            // do something appropriate
        }
    }
}

documentation 说:

预防措施仅对正式协议中的可选方法或非正式协议中的方法是必要的

这是什么意思?如果我使用正式协议,我可以使用[delegate myMethod]?

【问题讨论】:

    标签: objective-c ios


    【解决方案1】:

    您几乎只在您认为需要时使用它:检查对象是否实现了您将要调用的方法。 通常当您有可选方法或非正式协议时会这样做。

    我只在编写必须与委托对象通信的代码时使用respondsToSelector

    if ([self.delegate respondsToSelector:@selector(engineDidStartRunning:)]) {
            [self.delegate engineDidStartRunning:self];
        }
    

    您有时希望在任何返回的方法上使用respondsToSelector,在您不确定返回对象的类是什么的情况下使用id 或通用NSObject

    【讨论】:

    • 谢谢。我现在知道了。我注意到您使用 self.delegate,这是一个属性。我只使用了一个实例变量:id delegate。有什么不同?我正在学习objective-c。再次感谢
    • self.delegate 与调用[self delegate] 完全相同。在我的代码中,[self.delegate someMethod][_delegate someMethod] 之间没有区别,但我倾向于使用点语法,因为它让我清楚地知道哪些变量是我所在方法的本地变量,哪些是实例变量。
    • 如果您刚刚开始,那么值得您花时间阅读 Apple 的 Obj-C 指南。 developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/…
    • 还有一个问题:需要在dealloc和viewDidUnload方法中设置delegate = nil吗?(是委托类还是实现委托的类?)
    • 没有。委托属性几乎应该总是被分配而不是保留。在绝大多数示例中,您不拥有委托对象,因此您不应保留或释放它。 stackoverflow.com/questions/918698/…
    【解决方案2】:

    只是补充一下@kubi 所说的,我使用它的另一次是在新版本的框架中将方法添加到预先存在的类中,但我仍然需要向后兼容。例如:

    if ([myObject respondsToSelector:@selector(doAwesomeNewThing)]) {
      [myObject doAwesomeNewThing];
    } else {
      [self doOldWorkaroundHackWithObject:myObject];
    }
    

    【讨论】:

      【解决方案3】:

      正如 kubi 提到的,respondsToSelector 通常在您拥有符合协议的方法的实例时使用。

      // Extend from the NSObject protocol so it is safe to call `respondsToSelector` 
      @protocol MyProtocol <NSObject> 
      
      // @required by default
      - (void) requiredMethod;
      
      @optional
      
      - (void)optionalMethod;
      
      @end
      

      给定这个协议的实例,我们可以安全地调用任何需要的方法。

      id <MyProtocol> myObject = ... 
      [myObject requiredMethod];
      

      但是,可选方法可能会也可能不会实现,因此您需要在运行时进行检查。

      if ([myObject respondsToSelector:@selector(optionalMethod)]) 
      {
           [myObject optionalMethod];
      }
      

      这样做可以防止因无法识别的选择器而崩溃。


      另外,你应该将协议声明为 NSObjects 的扩展的原因,即

      @protocol MyProtocol <NSObject> 
      

      是因为 NSObject 协议声明了respondsToSelector: 选择器。否则 XCode 会认为调用它是不安全的。

      【讨论】:

      • 我只是忘了添加 解决了我的问题,谢谢
      【解决方案4】:

      老问题,但我学会了在使用 addTarget:@selector(fu:) 之类的东西时非常谨慎,因为 XCODE 不会检查方法名称,也不会将其包含在重构中。这已经给我带来了一些麻烦。所以现在我养成了在 respondsToSelector-Check 中嵌入 addTarget 或 addObserver 之类的习惯,如下所示:

      if([self respondsToSelector:@selector(buttonClicked:)]){
          [self.button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
      }else{
          DebugLog(@"Warning - a class or delegate did not respond to selector in class %@", self);
      } 
      

      我知道它不是超级优雅,但我宁愿添加一些样板代码,也不愿让我的应用在 App Store 中意外崩溃。

      【讨论】:

      • 我认为“methodName:”现在已在 xCode 中的 @selector(methodName:) 等语句中进行检查,不是吗?
      • @Grezzo - XCode 只会检查选择器是否存在于目标中的某个位置。例如,如果你写了@selector(date) 而不是@selector(data) XCode 不会警告你,因为date 选择器存在于NSDateComponents
      猜你喜欢
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      相关资源
      最近更新 更多