我是Objective C的新手,我正试图直接调用对象的数组(NSArray)上的方法:
[[myPeople objectAtIndex: 0] setName: @"Shane"];
但这似乎不起作用,并返回一条警告,说“已找到多个名为'setName'的方法”
我可以这样成功地执行操作:
Person* person = [myPeople objectAtIndex: 0];
[person setName: @"Shane"];
我的语法在第一种情况下是不正确的,还是应该使用第二段代码?或者有更好的方法我不知道吗?
谢谢,非常感谢任何帮助
答案 0 :(得分:8)
您可以像这样对数组中的所有对象执行此操作:
[myPeople makeObjectsPerformSelector:@selector(setName:) withObject:@"Shane"];
答案 1 :(得分:3)
第一种语法是正确的,尽管有警告,但仍能正常工作。编译器警告您,因为它无法验证您正在调用setName:
的对象类型。
objectAtIndex:
类的方法NSArray
返回类型id
,它是指向未知类型的Objective-C对象的通用指针。因此,当您在返回的setName:
上调用id
时,编译器不知道该对象的实际类是什么。在您的代码中,有多个类定义setName:
方法(可能作为名为name
的属性的合成setter),因此它会发出警告。
第二个代码片段在没有警告的情况下编译,因为id
类型可以隐式地转换为任何其他Objective-C指针类型。当您说Person* person = [myPeople objectAtIndex: 0];
时,您正在接受id
返回的objectAtIndex:
并将其(隐式)投射到Person*
。然后,当您在setName:
上调用Person
时,编译器会知道您拥有的类型,因此它可以验证类Person
实际上是否实现了setName:
方法。
答案 2 :(得分:3)
如果要绕过编译器警告。还有另外两种方法,然后是你演示的方法。
你可以调用performSelector:withObject。
[[myPeople objectAtIndex: 0] performSelector:@selector(setName:) withObject: @"Shane"];
通常使用此方法,您需要确保它响应选择器。
if ([[myPeople objectAtIndex: 0] respondsToSelector:@selector(setName:)])
另一种选择是投射结果
[(Person*)[myPeople objectAtIndex: 0] setName: @"Shane"];
这些应该消除编译器警告。