Подтвердить что ты не робот

Нужно ли использовать слабые ссылки на себя всегда внутри блоков..?

Я запутался в использовании внутренних блоков, я просматриваю некоторые документы Apple, но не могу найти правильный ответ.

Некоторые люди всегда говорят, что используют слабый внутренний блок внутри, но некоторые говорят, что используют слабое я в блоках, которые скопированы, а не всегда для использования всегда.

Пример 1:

self.handler = ^(id response, NSError *error)
{
    self.newresponse = response; //use weak self here
};  

Пример 2:

Используя слабый я,

__weak myViewController *weakSelf = self;

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
    [weakSelf.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];
    //in above is it use of weak is neassary 
}
completion:^(BOOL finished)
{

}];

Без слабой самости;

__weak myViewController *weakSelf = self;

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
    [myViewController.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];

}
completion:^(BOOL finished)
{

}];

В приведенных выше примерах, которые являются правильными...? ** Я использую ARC

4b9b3361

Ответ 1

Вы должны использовать только слабую ссылку на self, если self будет удерживать ссылку на блок.

В вашем примере вы не сохраняете ссылку на свой блок в self, вы используете только встроенные блоки с UIView animateWithDuration:, и поэтому нет необходимости использовать __weak myViewController *weakSelf = self;

Почему это так? Поскольку блок сохранит сильные ссылки на любые переменные, которые он использует из класса с использованием блока. Это включает self. Теперь, если сам экземпляр класса сохраняет сильную ссылку на блок, и блок сохраняет сильную ссылку на экземпляр класса, у вас есть цикл сохранения, который будет вызывать утечки памяти.

Ответ 2

Вот код, который демонстрирует ответ @WDUK:

typedef void (^SimpleBlock)();

@interface ObjectThatRetainsBlock : NSObject
@property(nonatomic, strong) SimpleBlock block;
@end

@implementation ObjectThatRetainsBlock

- (instancetype)init {
  self = [super init];
  if (self) {
    self.block = ^{ NSLog(@"Running block in %@", self); };
    self.block();
  }
  return self;
}

- (void)dealloc {
  NSLog(@"ObjectThatRetainsBlock is deallocated.");
}

@end

@interface ObjectThatDoesNotRetainBlock : NSObject
@end

@implementation ObjectThatDoesNotRetainBlock

- (instancetype)init {
  self = [super init];
  if (self) {
    SimpleBlock block = ^{ NSLog(@"Running block in %@", self); };
    block();
  }
  return self;
}

- (void)dealloc {
  NSLog(@"ObjectThatDoesNotRetainBlock is deallocated.");
}

@end

- (void)test {
  ObjectThatRetainsBlock *objectThatRetainsBlock =
      [[ObjectThatRetainsBlock alloc] init];
  ObjectThatDoesNotRetainBlock *objectThatDoesNotRetainBlock = 
      [[ObjectThatDoesNotRetainBlock alloc] init];
}

Метод test печатает:

Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50>
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50>
ObjectThatDoesNotRetainBlock is deallocated.

Обратите внимание, что в init методе ObjectThatDoesNotRetainBlock мы создаем block как ivar, но когда block выходит за рамки, мы не будем ссылаться на него.

В методе test, когда два объекта выходят из области видимости, обратите внимание, что ObjectThatDoesNotRetainBlock освобождается, поскольку он не является частью цикла сохранения.

С другой стороны, objectThatRetainsBlock не освобождается, поскольку он является частью цикла сохранения. Он сохраняет этот блок за пределами вызова метода.

Если вы хотите получить другое объяснение, см. этот ответ.