Доступ к назначенному свойству делегата из блока Objective-C? (IOS) - PullRequest
2 голосов
/ 24 февраля 2012

Можно ли получить доступ к свойству делегата из блока?

@interface TheObject : NSObject
...
@property (nonatomic, assign) id<SomeDelegate> delegate;

@synthesize delegate

- (void) someMethod {
  [someObject doSomethingWithCompletionHandler:^(NSArray *)someArray {
      [self.delegate otherMethod:someArray];   
 }];
}

Что произойдет, если делегат очищается (из метода dealloc в объекте, который также установил делегат) до вызова обработчика завершения? Может ли это быть ошибка памяти? Я не знаю, как использовать __block для свойств ...

Ответ снизу:

Если делегат очищен от объекта, который является делегатом в вызове dealloc, все в порядке.

@property (nonatomic, retain) TheObject theObject;

@synthezise theObject = _theObject;

- (void) thatMethod {
  self.theObject = [[TheObject alloc] init] autorelease];
  _theObject.delegate = self;
}

- (void) dealloc {
  _theObject.delegate = nil;
  self.theObject = nil;
}

Ответы [ 2 ]

3 голосов
/ 24 февраля 2012

Обычно, если ваш delegate освобожден до выполнения блока, он получит доступ к мусору, поскольку блок является свойством assign и блок сохраняет self, а не delegate, так как вы обращаетесь к немупо ссылке.

Однако, поскольку вы настроили его так, что self.delegate обнуляется, если delegate освобожден, у вас не будет этой проблемы.Вместо этого, если ваш delegate был освобожден, то в вашем коде вы просто отправляете метод otherMethod: на nil, который ничего не будет делать, но также не вызовет ошибок.

Если вы хотитеметод, который обязательно должен быть отправлен вашему delegate, решение состоит в том, чтобы получить доступ к нему по значению вместо ссылки:

- (void)someMethod {
    id <SomeDelegate> delegateForBlock = self.delegate;
    [someObject doSomethingWithCompletionHandler:^(NSArray *)someArray {
        [delegateForBlock otherMethod:someArray];   
    }];
}

Таким образом delegateForBlock будет указателем на тот же объект, что и self.delegate(во время выполнения someMethod:), и он будет сохранен.

Чтобы узнать больше о том, как это работает, ознакомьтесь с Blocks Programming Topics .

0 голосов
/ 24 февраля 2012

Если делегат освобожден, вы получите доступ к мусорному значению, которое приведет к EXC_BAD_ACCESS.

. Вы можете либо сделать

id <SomeDelegate> dlg = self.delegate
[someObject doSomethingWithCompletionHandler:^(NSArray *)someArray {
  [dlg otherMethod:someArray];   
}];

, либо напрямую получить доступ к ивару, поэтомучто блок сохраняет его

[someObject doSomethingWithCompletionHandler:^(NSArray *)someArray {
  [delegate otherMethod:someArray];   
}];
...