2

当您使用 检索选择器的 ID 时,选择@selector()器值是否因参数类型而异?

这就是我的意思。我有一个接受对象引用和选择器的方法,然后使用参数调用它:

-(void)CallLater:(NSObject*) Obj Sel: (SEL)Sel
{
    //Some stuff, then:
    [Obj performSelector: Sel withObject: SomeOtherObject];
}

我将此方法与一个选择器一起使用到一个函数,该函数接受一个类型化的对象引用,而不是id

-(void)MyMethod: (MyObject*) a
{
}

[self CallLater: self Sel:@selector(MyMethod:)];

它似乎有效,但我的感觉正在刺痛。在像 C# 这样的静态类型语言中,这将是一种犯规,一种向上转型 -CallLater期望一个选择器用于一个接受 a 的函数,id而我给它一个接受 a 的函数MyObject

另一方面,编译器并没有抱怨,id而且具体的对象引用似乎都只是深层的指针,可以简单地相互转换。话又说回来,Objective C 编译器没有抱怨很多错误。

所以真正的问题是——它安全吗?欢迎语言律师。

4

1 回答 1

3

它是安全的; 对象是对象。anNSObject *的选择器参数与 a 的选择器参数完全相同MyObject *

如果您希望 MyMethod 验证它是使用特定类型的对象调用的,它应该对其执行 NSParameterAssert :

NSParameterAssert([obj isKindOfClass: [MyObject class]]);

就个人而言,我很少做这个检查。实际对象的行为就像我想要的类型就足够了,如果不是,我会得到一个运行时错误(通常是无法识别的选择器)。在简单的情况下,您会收到编译器警告,值得关注此警告(并在必要时使用 id 强制转换使其静音)。

我对您id在问题中的使用感到有些困惑,所以我想确保您理解这一点: An和aNSObject *一样多。是一个通用实例指针类,而是一个实例(或 的子类)。您可以拥有不从. 但你不太可能知道这一点。idMyObject *idNSObject *NSObjectNSObjectNSObject

其他注意事项,重新:约定:

  • Selectors (both the name and parameters) start with lowercase letters, so CallLater:Sel: should be callLater:sel:.
  • Variable and parameter names start with lowercase letters; Obj above should be obj.
  • Class names do start with an uppercase letter. :)
于 2012-07-20T01:55:12.173 回答