Переопределение isEqual: метод, но он не вызывается при удалении объекта из массива. - PullRequest
3 голосов
/ 25 декабря 2011

Я использую xCode 4.2 и прохожу книгу «Программирование в Objective C 2.0»

Существует упражнение, включающее реализацию метода isEqual: из класса NSObject.

В книге говорится, что метод isEqual: запускается при вызове метода removeObjectIdenticalTo: класса NSArray.removeObjectIdenticalTo: заканчивается отправкой сообщения isEqual: всем членам массива.

Когда я пытаюсь реализовать этот метод isEqual: в моем классе AddressCard, и я использую removeObjectIdenticalTo:, передавая объектэто экземпляр класса AddressCard, однако мой метод isEqual: не вызывается.Хотя если я просто использую метод isEqual: для экземпляра AddressCard явно, он работает.

Вот мой метод isEqual: из файла AddressCard.m

-(BOOL)isEqual: (id)object {
    NSLog(@"I got called");
    return NO;
}

Когда этот код запускается в AddressBook.m

-(void) removeCard: (AddressCard *) theCard {
    [book removeObjectIdenticalTo: theCard];
}

, указанный выше метод isEqual: не вызывается.

Мне кажется, что я упускаю что-то важное, но из всего, что я прочитал и знаю, я думаю, что isEqual: ДОЛЖЕН быть вызван, если removeObjectIdenticalTo: больше не затрагивает это.

У меня есть все соответствующие методы, определенные в файлах .h.

Ответы [ 2 ]

8 голосов
/ 25 декабря 2011

Как вы уже догадались, removeObjectIdenticalTo: не вызывает isEqual:, поскольку просто использует адреса объектов для проверки равенства.

Но removeObject: вызывает isEqual:, так что вы, скорее всего, захотите.

6 голосов
/ 25 декабря 2011

Похоже, книга ошиблась.

NSMutableArray и другие коллекции имеют несколько пар похожих методов, таких как removeObject: и removeObjectIdenticalTo:, с важными различиями в их значениях.

Первый тест проверяет, совпадают ли значения объектов в коллекции со значением переданного объекта. Для этого массив вызывает isEqual: для каждого объекта в массиве. Это позволяет каждому классу определить для себя, что означает «равенство» с другим объектом, как вы делаете для своего AddressCard класса. Подробности о removeObject: можно найти в его документации :

Этот метод использует indexOfObject: для поиска совпадений [...] Таким образом, совпадения определяются на основе ответа объекта на сообщение isEqual:.

Методы ...IdenticalTo: имеют дело с фактической идентичностью в памяти объектов. Они проверяют, совпадает ли адрес переданного объекта с адресом любого объекта в коллекции. Массив может найти адрес объекта без вызова каких-либо методов для этого объекта; isEqual: здесь не используется. Опять же, это указано в документах :

Этот метод использует метод indexOfObjectIdenticalTo: для поиска совпадений [...] Таким образом, совпадения определяются с использованием адресов объектов.

Вообще говоря, вам понадобится removeObject: гораздо чаще, чем removeObjectIdenticalTo:, поскольку его значение наиболее точно соответствует действию, которое вы хотите выполнить: выберите объект, значение которого совпадает с указанным объект.

...