Вызов super в реализации блока Objective-C - PullRequest
11 голосов
/ 12 декабря 2010

Поддерживается ли вызов метода для super при реализации блока Objective-C?

Когда я вызывал метод на super , возникала ошибка EXC_BAD_ACCESS , но как только я изменил эти вызовы с [super methodToCall] на [self methodToCall], и сообщение переместилось до цепочки респондента это работало нормально.

В экземпляре класса, в котором существует блок, нет реализации -methodToCall, но в суперклассе есть класс (то есть класс, от которого наследуется self).

Мне просто любопытно узнать подробности о том, почему вызов метода super внутри реализации блока был проблемой в первую очередь (технически), поэтому я могу избежать этого в будущем. У меня есть подозрение, что это связано с тем, как переменные записываются в блок, и что-то со стеком и кучей, но я действительно не имею конкретной идеи.

Примечание: код реализации блока вызывается через несколько секунд после сохранения блока в свойстве, свойство использует copy , поэтому я не думаю, что это проблема жизненного цикла блока, что все выглядит хорошо. Кроме того, это было только сбой на устройстве iPhone (3G), но работал без сбоев в симуляторе iPhone.

Результаты в EXC_BAD_ACCESS:

[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
 if (!error) {
  [super didRetrieveItems];
 } else {
  [super errorRetrievingItems];
 }
}];

Работает отлично, реализации -didRetrieveItems и -errorRetrievingItems в суперклассе.

[self retrieveItemsForId:idString completionHandler:^(NSError *error) {

 if (!error) {
  [self didRetrieveItems];
 } else {
  [self errorRetrievingItems];
 }
}];

Ответы [ 2 ]

11 голосов
/ 12 декабря 2010

Технически, это проблема среды выполнения Objective-C и основной механики того, как на самом деле работают вызовы super. По сути, они захватывают как объект, который является получателем сообщения (self во всех случаях), так и класс, который реализует конкретную версию метода (суперкласс класса, в котором происходит реализация метода). Поскольку большая часть подготовки к отправке такого сообщения происходит во время компиляции, а не во время выполнения, я не удивлюсь, если он плохо взаимодействует с блоками.

Я бы проверил, если self все еще действует, когда сообщение должно быть отправлено. Обычно любые объекты, на которые есть ссылки в блоке, автоматически сохраняются. Поскольку super работает немного по-другому, это может означать, что self не сохраняется, как можно было бы ожидать. Один из простых способов проверить это - использовать вызовы super, как изначально написано, и просто утечь объект, называемый self, и посмотреть, работает ли он. Если это оказывается проблемой, вам может понадобиться вставить фиктивную ссылку на self внутри блока, чтобы получить это автоматическое управление памятью.

В самом строгом смысле, однако, я не уверен, что вы можете зависеть от этой работы всегда и всегда. Хотя блоки могут захватывать текущее состояние времени выполнения, для них не имеет смысла (с точки зрения ООП) нарушать инкапсуляцию и вызывать реализации суперкласса, поскольку иерархический уровень , на котором реализуются методы, должен быть непрозрачным на любой внешний код вызова. Я бы попытался найти другое решение, которое не зависит от иерархии наследования.

8 голосов
/ 12 декабря 2010

Результаты в EXC_BAD_ACCESS:

[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
 if (!error) {
  [super didRetrieveItems];
 } else {
  [super errorRetrievingItems];
 }
}];

Возможно, из-за ошибки в компиляторе;попробуйте добавить [self class]; или любой другой вызов метода для self в этом блоке, и он, вероятно, будет работать.

Работает отлично, реализации -didRetrieveItems и -errorRetrievingItems находятся в суперклассе.

[self retrieveItemsForId:idString completionHandler:^(NSError *error) {

 if (!error) {
  [self didRetrieveItems];
 } else {
  [self errorRetrievingItems];
 }
}];

Я думаю, вы можете запутаться в одном из фундаментальных аспектов объектно-ориентированного программирования.Вы говорите, что в вашем классе нет реализаций этих методов, они существуют только в суперклассе.

Из-за наследования ваш класс также эффективно реагирует на вызовы указанных методов.Просто позвоните им, как вы делали выше, используя self.Это будет работать, найти и именно так, как вы должны это делать!

...