makeObjectsPerformSelector:

时间:2009-02-18 22:04:57

标签: objective-c arrays cocoa nsarray

我想让数组中的所有对象都执行选择器。我发现了适当命名的makeObjectsPerformSelector:方法,但我有一个问题。如果我在数组上使用它,它会更改现有数组还是返回一个新数组?如果它修改了现有对象,那么在应用选择器的情况下返回新数组的最简单方法是什么?

5 个答案:

答案 0 :(得分:29)

makeObjectsPerformSelector:将针对数组中的每个对象运行该选择器。如果选择器修改了这些对象,则会修改它们。它没有返回任何东西。现在,有一个catch,默认情况下,Cocoa中的大多数副本都是浅拷贝,这意味着你得到一个新的数组,但它指向的底层对象是相同的对象。您将需要使用initWithArray:copyItems来复制根级项目。如果你想要一个包含已更改对象的新数组以及旧数组,请执行以下操作:

NSArray *newArray = [[NSArray alloc] initWithArray:oldArray copyItems:YES];
[newArray makeObjectsPerformSelector:@selector(doSomethingToObject)];

答案 1 :(得分:15)

  

如果我在数组上使用它,它会更改现有数组还是返回一个新数组?

没有

首先,阅读签名:

- (void)makeObjectsPerformSelector:(SEL)aSelector

void,之后没有明星,意味着“不会返回任何东西”。

其次,请注意,这是NSArray的一种方法,它是一个不可变类。因此,makeObjectsPerformSelector:不会改变接收数组,因为这是不可能的。

有NSMutableArray,因为它是NSArray的子​​类,所以它继承了makeObjectsPerformSelector:。但是,如果NSMutableArray更改了该方法的行为,则其文档将具有自己的方法列表(请参阅各种类文档中的init的许多定义)。没有此类列表,因此您可以安全(并且正确)推断-[NSMutableArray makeObjectsPerformSelector:]的工作方式与-[NSArray makeObjectsPerformSelector:]完全相同。

对象可以自行修改以响应您的消息,但是数组本身将在makeObjectsPerformSelector:之后包含与之前相同的对象。

答案 2 :(得分:7)

除了其他答案之外,如果你想要创建一个调用方法的结果的新数组,你可以这样做:

NSArray *derivedArray = [originalArray valueForKey:@"foo"];

如果你的对象可以处理'-valueForKey:@“foo”'消息,那么只会工作,显然,它只适用于不带参数且返回非零值的方法。

答案 3 :(得分:2)

我希望我正确地解释这个......

如果你[myArray makeObjectsPerformSelector:someSelector],你实际上只是迭代myArray并将选择器消息发送到每个对象。数组未更改,因为不允许makeObjectsPerformSelector更改其内容。

所以最后,你得到了具有相同对象的相同数组。

答案 4 :(得分:0)

在下面的示例中,您可以看到已创建一个superView并添加了10个子视图,然后向每个视图发送removeFromSuperViewview类中存在的一种方法)结果是superView中的子视图为零。

如果您熟悉JavaScript并尝试在JavaScript中找到类似map的东西,那就不是那样了。 map在数组的每个元素上运行一个函数,并将其替换为结果,但此处makeObjectsPerformSelector在数组的每个对象中运行一个方法。

UIView* superView = [[UIView alloc] initWithFrame:CGRectZero];

for(int i = 0; i < 10; i++){
    UIView* view = [[UIView alloc] initWithFrame:CGRectZero];
    [superView addSubview:view];
}

NSLog(@"count = %lu", (unsigned long)[superView.subviews count]); // 10
[superView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; // removeFromSuperview is exist in `view`, you can call [view removeFromSuperview];
NSLog(@"count = %lu", (unsigned long)[superView.subviews count]); // 0