2

enter image description here У меня есть объект, и он использует делегатский блок. Я использую ARC.Слабая ссылка на self in block вызывает иногда BAD_EXCESS

@implementation ViewController 

- (void)createGame 
{ 
    _game = [[MRCircusGame alloc] init]; 
    _game.mainView = self.view; 
    _game.stageObjectsDictionary = [self getStageObjectsDictionary]; 
    [_game prepareGame]; 
} 

- (NSMutableDictionary *)getStageObjectsDictionary 
{ 
    StrongMan *strongMan = [[StrongMan alloc] initAndCreateImageViewWithFrame:kStrongManIntroFrame inView:self.view]; 
    strongMan.isTakingTouches = NO; 
    strongMan.isVisible = NO; 
    [tempDictionary setObject:strongMan forKey:kMRCircusStrongMan]; 
    return tempDictionary; 
} 

@interface MRCircusGame 
{ 
@property (nonatomic, strong) NSMutableDictionary *stageObjectsDictionary; 
} 

@implementation StrongMan 
.. 
-(void)method 
{ 
    __weak typeof (self) weak_self = self; 
    self.animator.didEndAnimating = ^{ 
      StrongMan *strongRef = weak_self; 
      strongRef.isAnimating = NO; 
      [strongRef idle]; 
    }; 
} 

Некоторые вопросы:

Если я не использую слабую ссылку на себя, Xcode делает некоторые предупреждения о возможном сохранить цикла. Но я смотрю на инструменты и никакой утечки Memery не было обнаружено даже я использую self.isAnimating = YES;

Если я не использую этот strongRef обходной путь, иногда я BAD_EXCESS, так что я думаю, что это weak_self был выпущен я прав? Должен ли я использовать strongRef все время, чтобы предотвратить падение моего приложения?

Будет ли strongRef освобожденным после завершения этого блока?

+0

Невозможно получить EXEC_BAD_ACCESS из кода, который вы указали.Да, если 'self' был освобожден до блокировки блока, тогда' weak_self' будет 'nil', и так будет' strongRef'. Но вы просто вызываете методы на 'strongRef', а методы вызова на' nil' - в Objective-C. У вас должна быть проблема где-то в другом месте. – newacct

+0

Кроме того, изображение, которое вы показываете, не соответствует вашему коду. Что он? – newacct

+0

Не должно быть ссылки внутри блока, чтобы быть слабым, а не самим собой? (внутри изображения) – mnl

ответ

2

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

инструментов будут показывать только недостижимый объект, если

  • использовать сильную ссылку на себя внутри блок
  • и вы не ноль ссылки на блок в dealloc
  • и вы NIL ссылка на StrongMan
+0

, поэтому я делаю это правильно. Приятно слышать. – alexhajdu

+0

или я должен использовать только себя и не забочусь о предупреждении? – alexhajdu

+0

Существует три способа прерывания циклов: 1) Scope: скопируйте переменную, чтобы вам не нужно ссылаться на self. 2) Программно: nil свойство блока, которое вызывает цикл сохранения. 3) Атрибуты: используйте слабую ссылку. Вы не можете использовать 1), потому что вам нужно установить свойство «я», но вы можете использовать 2 или 3 по вашему выбору. Я предпочитаю 3), поэтому мне не нужно ничего забывать позже. – Jano

-1

Правильный способ сделать это, чтобы получить доступ к переменным экземпляра непосредственно:

_animator.didEndAnimating = ^{ .... }; 
+0

аниматор - свойство StrongMan super class – alexhajdu

+0

ther без проблем с аниматором, но с исполнением кода внутри блока – alexhajdu

+1

@mundi :: как это важно? * Поистине любопытно * –

0

При использовании слабых ссылок и экземпляр StrongMan освобождается до анимации останавливается ваше приложение будет врезаться. Чтобы предотвратить сбой, вы должны удалить ссылку, когда объект будет освобожден. Используя следующий код в методе dealloc должен это сделать:

self.animator.didEndAnimating = nil; 
+0

не нужно. AFAICS __weak будет забито, когда сам уйдет, нет? –

+0

Да, вы правы. На какой строке вы получаете BAD_EXCESS? – murat

1

я испытал подобную проблему раньше. Основной причиной проблемы является то, что объект освобождается до окончания анимации. Поэтому, когда блок выполняется, ссылающегося «я» не существует.

Я думаю, что есть два пути решения этой проблемы:

  1. Вы переопределить метод «dealloc», а затем присвоить ноль для self.animator.didEndAnimating. Поэтому после анимации ничего не выполняется.

  2. В блоке вы можете проверить, что погода «я» равна нулю или нет, а затем делать то, что вы хотите.

+0

1 будет работать, 2 я не получаю .. но опять АФАИКС это не нужно. __weak vars нули, нет? –

+0

1) Мне действительно нужно выполнить весь блок после завершения анимации. 2) Возможно, это сработает, но лучше не работать с сильной ссылкой на слабину с самого начала? – alexhajdu

+0

@alexhajdu, тогда в этом случае проблема заключается в освобождении объекта. Как вы храните этот объект? Я думаю, что мы говорим о «представлении» в этом случае, поэтому, если вы назначите свое представление сильной переменной контроллера вида, ваша проблема может быть решена, насколько я понимаю. –

Смежные вопросы