makeObjectsPerformSelector:
-
05-09-2019 - |
Вопрос
Я хочу, чтобы все объекты в массиве выполняли селектор.Я обнаружил подходящее название makeObjectsPerformSelector:
метод, но у меня есть вопрос по нему.Если я использую его в массиве, изменится ли он существующий массив или вернет новый?Если он изменяет существующий объект, какой самый простой способ вернуть новый массив с примененным селектором?
Решение
makeObjectsPerformSelector:собирается запустить этот селектор для каждого объекта в массиве.Если эти объекты будут изменены селектором, они будут изменены.Он ничего не возвращает.Есть одна загвоздка: по умолчанию большинство копий в Cocoa являются поверхностными копиями, что означает, что вы получаете новый массив, но базовые объекты, на которые он указывает, являются теми же объектами.Вам нужно будет использовать initWithArray:copyItems, чтобы он также копировал элементы корневого уровня.Если вам нужен новый массив, содержащий измененные объекты, а также старый массив, сделайте что-то вроде этого:
NSArray *newArray = [[NSArray alloc] initWithArray:oldArray copyItems:YES];
[newArray makeObjectsPerformSelector:@selector(doSomethingToObject)];
Другие советы
Если я использую его в массиве, изменится ли он существующий массив или вернет новый?
Нет.
Для начала прочитайте подпись:
- (void)makeObjectsPerformSelector:(SEL)aSelector
void
, без звездочек после него, означает «ничего не возвращает».
Во-вторых, обратите внимание, что это метод NSArray, который является неизменяемым классом.Поэтому, makeObjectsPerformSelector:
не изменяет принимающий массив, потому что это невозможно.
Существует NSMutableArray, и поскольку это подкласс NSArray, он наследует makeObjectsPerformSelector:
.Однако, если NSmutableArray изменит поведение этого метода, в его документации будет собственный список этого метода (см. многочисленные определения init
в документации различных классов).Такого списка нет, поэтому вы можете безопасно (и правильно) сделать вывод, что -[NSMutableArray makeObjectsPerformSelector:]
работает точно так же, как -[NSArray makeObjectsPerformSelector:]
.
Объекты могут изменяться в ответ на ваше сообщение, но сам массив будет содержать те же объекты после makeObjectsPerformSelector:
как и прежде.
В дополнение к другим ответам, если вы делать хотите создать новый массив с результатом вызова метода, вы можете сделать это:
NSArray *derivedArray = [originalArray valueForKey:@"foo"];
Это будет только работает, если ваши объекты могут обрабатывать сообщение '-valueForKey:@"foo"' и, очевидно, подходят только для методов, которые не принимают аргументов и возвращают ненулевое значение.
Надеюсь, я правильно это интерпретирую...
Если вы выполните [myArray makeObjectsPerformSelector:someSelector], вы фактически просто перебираете myArray и отправляете сообщение селектора каждому объекту.Массив не изменяется, поскольку makeObjectsPerformSelector не имеет права изменять его содержимое.
В итоге у вас есть тот же массив с теми же объектами.
В следующем примере вы можете увидеть один superView
создается и к нему добавляется 10 подпредставлений, затем в каждое из них отправляется removeFromSuperView
(метод, существующий в view
class) и результатом является нулевой подпредставление в superView
.
Если вы знакомы с JavaScript и пытаетесь найти что-то вроде map
в JavaScript это не так. 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