它是否正确?使用performSelector而不是直接调用方法

时间:2011-10-15 17:38:43

标签: ios cocoa-touch performselector

我正在尝试使用此方法[self.superview buttonPressedClose];

关闭超级视图

我已经在我的superview中实现了这个方法,一切正常。

但它在编译期间给了我一个警告“ UIView可能无法响应'buttonPressedClose'”。

如果我将其更改为以下行,它不会给我提醒,但这是正确的方法吗?

if ([self.superview respondsToSelector:@selector(buttonPressedClose)]) {
    [self.superview performSelector:@selector(buttonPressedClose) withObject:nil afterDelay:0.0];
}

感谢。

**编辑错字..

2 个答案:

答案 0 :(得分:4)

这是一个错误的问题还是在您的代码中?

if ([self.superview respondsToSelector:@selector(buttonPressedClose)]) {
                                                   //  vv here
[self.superview performSelector:@selector(buttonPressedCLose) withObject:nil afterDelay:0.0];
}

通常,self.superview会返回UIView类型的对象,而您的buttonPressedCloseUIView中未实现的自定义选择器。这就是你收到警告的原因。

您可能希望将self.superview投射到所需类型,例如:

[(MyView *)self.superview buttonPressedClose];

或使其变得更加神秘并转向id - 编译器不会检查选择器是否存在:

[(id)self.superview buttonPressedClose];

尽管如此,上述所有解决方案都有点臭。

关于performSelector:的一个非常重要的事情,没有延迟 - 它不会执行选择器,而是将选择器执行发布到线程的运行循环并在控制返回时执行它运行循环(即调用堆栈为空时)。所以在正常情况下你不想使用它。

答案 1 :(得分:0)

“这是正确的方法吗?”

不,没有理由这样做。 afterDelay:0仅在您不想立即执行时使用。如果您想立即执行,则应使用performSelector:而不使用afterDelay:

但是像这样直接使用performSelector:没有任何好处。它等同于,并且是一种更复杂的方式,直接调用该方法。您收到的警告纯粹是一种静态类型检查问题。类型(UIView *)不保证具有该方法。您需要将其强制转换为支持该方法的预期视图类型,或将其强制转换为id以关闭方法检查。当你使用performSelector:时,它也绕过方法的静态类型检查,所以它绝对不比将其转换为id然后调用它更好。