Короче говоря: вы можете использовать __strong
ссылку на себя в dealloc
вместо __weak
для ваших целей, но если и только если эта сильная ссылка не переживет конец dealloc
. В противном случае я бы посоветовал использовать __unsafe_unretained
, который по-прежнему небезопасен, если он переживает dealloc
, но более читается.
Дольше: у меня была аналогичная ситуация, когда объект (контроллер просмотра) во время dealloc должен отписаться от уведомлений. Это настраиваемая система уведомлений, и отмена подписки требует создания объекта со ссылкой на сущность, которая не подписана. я в конечном итоге с той же ситуацией: в dealloc нет никакого способа, чтобы создать этот объект, поскольку он требует слабой ссылки, который вызвал аварию (вот какой-то глупый демо-код, а не то, что вы бы в производстве):
@interface Dummy : NSObject
@property(nonatomic, weak) id weakProperty;
@property(nonatomic, strong) id strongProperty;
@property(nonatomic, unsafe_unretained) id unsafeProperty;
- (instancetype)initWithWeakStuff:(id)stuff;
- (instancetype)initWithStrongStuff:(id)stuff;
- (instancetype)initWithUnsafeStuff:(id)stuff;
@end
@implementation Dummy
- (instancetype)initWithWeakStuff:(id)stuff {
self = [super init];
if (self) {
_weakProperty = stuff;
}
return self;
}
- (instancetype)initWithStrongStuff:(id)stuff {
self = [super init];
if (self) {
_strongProperty = stuff;
}
return self;
}
- (instancetype)initWithUnsafeStuff:(id)stuff {
self = [super init];
if (self) {
_unsafeProperty = stuff;
}
return self;
}
- (void)dealloc {
}
@end
@interface ViewController()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
Dummy *dummy = [[Dummy alloc] initWithStrongStuff:self];
[[NSNotificationCenter defaultCenter]
postNotificationName:@"some notification"
object:dummy]; // do something with it
}
@end
Если, с другой стороны, ссылка была сильной, все, похоже, хорошо работает (во время dealloc). Проблема возникнет, если что вновь созданный объект переживет себя:
- (void)dealloc {
Dummy *dummy = [[Dummy alloc] initWithStrongStuff:self];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter]
postNotificationName:@"some notification"
object:dummy]; // do something with it
}); //Crash at the end of the block during dummy's dealloc
}
Это означало бы, что всякий раз, когда dummy
объект должен был бы dealloc он будет пытаться уменьшить количество реф его strongProperty
. И в этот момент ViewController
был освобожден и выпущен уже. Тем не менее, ИМХО является «самым безопасным» способом для использования в этом случае unsafe_unretained
. Технически это то же самое, что и использование assign: указатель будет назначен независимо от управления памятью, и эта ссылка не будет выпущена, когда она выходит за рамки. Но с помощью unsafe_unretained
рассказывают читателям вашего кода (или будущего вас), что вы знали об этом риске, и, должно быть, были причины делать то, что вы делали.
Если ваш объект (именуемый 'self') освобождается, зачем вам вообще уменьшать' dlcounter'? Он скоро даже не существует - вам нужно использовать его позже в методе 'dealloc'? –
Вы действительно не должны делать эту работу в dealloc.Вызовите 'cancelAllPendingDownloads' перед деаллоцированием. – zaph
Из-за темы, почему в этом примере рекомендуется использовать ссылку '__weak' для' self'? 'dl' является экземпляром в объеме метода, не сохраняемым' self', поэтому должно быть хорошо использовать 'self' внутри блока, правильно? Это только для предотвращения запуска 'self.dlcounter -', если 'self' уже освобожден? В этом случае блок не сохраняет self, поэтому он сохраняет его в живых (в случае использования 'self' внутри блока). Спасибо –