使用 self 时块何时会导致保留循环?
When Do Blocks Cause Retain Cycles When Using Self?
我的应用程序中存在一些内存泄漏问题,我想知道块是否与它有关。我读过在块中使用 Self 会导致保留循环,但是我读过关于何时发生的相互矛盾的信息。
据我了解,做这样的事情:
dispatch_async(dispatch_get_main_queue(), ^{
self.text = @"test";
[self doSomething];
});
或
[self.dataArrayOfDictionaries enumerateObjectsUsingBlock:^(NSDictionary *vd, NSUInteger idx, BOOL *stop) {
[self doSomethingWithDictionary:vd];
}];
会保留自我,直到完成某些事情,比如这样的事情:
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
NSError *err;
self.myDataArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
将保留自我,直到下载完成并重新加载 table 视图。因此,虽然这段代码保留 Self 的时间可能超过所需的时间,但它不会无限期地保留它,对吗?
此外,我假设如果在完整的块中引用了 self,这会导致保留循环,因为该块由 self 保留...对吗?
@interface MyViewController
@property (strong, nonatomic) void (^complete)(NSData *results);
@end
@implementaiton MyViewController
[self doStuffWithCompletion:self.complete];
我不确定保留周期的地方是这样的。
[[NSNotificationCenter defaultCenter]addObserverForName:@"thingDone" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
self.dataObject = note.object;
}];
我听说 NSNotificationCenter 不会保留它的观察者,但是因为这个函数永远不会像前两个函数那样 "completed" 我觉得它可能会保留 Self。此外,如果我改用 weakSelf,如果收到通知并且 self 已被解除分配,应用程序不会崩溃吗,因为 weakSelf 将为零?
我在导航控制器中有一个视图控制器,它在点击 back/popping 时没有解除分配,我认为这可能是因为保留周期。如果有人能澄清我对何时在块中使用 Self 是 acceptable 的理解,那将对我的代码有很大帮助。
Where I am not sure about retain cycles is in something like this
[[NSNotificationCenter defaultCenter]addObserverForName: //...
是的,可能存在与调用 addObserverForName:
相关的内存管理问题。正如我解释的 in my book:
调用 addObserverForName:object:queue:usingBlock:
返回的观察者令牌由通知中心保留,直到您注销它。
观察者令牌也可能会在整个区块中保留您。如果是这样,那么直到您从通知中心取消注册观察者令牌,通知中心才会保留您。这意味着您将泄漏,直到您注销。但是你不能在dealloc
的通知中心注销,因为只要你注册了dealloc
就不会被调用
此外,如果你还保留观察者令牌,那么如果观察者令牌正在保留你,你手上就有一个保留周期。
您可能想阅读我书中的其余讨论以获取实际示例和解决方案。
我的应用程序中存在一些内存泄漏问题,我想知道块是否与它有关。我读过在块中使用 Self 会导致保留循环,但是我读过关于何时发生的相互矛盾的信息。
据我了解,做这样的事情:
dispatch_async(dispatch_get_main_queue(), ^{
self.text = @"test";
[self doSomething];
});
或
[self.dataArrayOfDictionaries enumerateObjectsUsingBlock:^(NSDictionary *vd, NSUInteger idx, BOOL *stop) {
[self doSomethingWithDictionary:vd];
}];
会保留自我,直到完成某些事情,比如这样的事情:
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
NSError *err;
self.myDataArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
将保留自我,直到下载完成并重新加载 table 视图。因此,虽然这段代码保留 Self 的时间可能超过所需的时间,但它不会无限期地保留它,对吗?
此外,我假设如果在完整的块中引用了 self,这会导致保留循环,因为该块由 self 保留...对吗?
@interface MyViewController
@property (strong, nonatomic) void (^complete)(NSData *results);
@end
@implementaiton MyViewController
[self doStuffWithCompletion:self.complete];
我不确定保留周期的地方是这样的。
[[NSNotificationCenter defaultCenter]addObserverForName:@"thingDone" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
self.dataObject = note.object;
}];
我听说 NSNotificationCenter 不会保留它的观察者,但是因为这个函数永远不会像前两个函数那样 "completed" 我觉得它可能会保留 Self。此外,如果我改用 weakSelf,如果收到通知并且 self 已被解除分配,应用程序不会崩溃吗,因为 weakSelf 将为零?
我在导航控制器中有一个视图控制器,它在点击 back/popping 时没有解除分配,我认为这可能是因为保留周期。如果有人能澄清我对何时在块中使用 Self 是 acceptable 的理解,那将对我的代码有很大帮助。
Where I am not sure about retain cycles is in something like this
[[NSNotificationCenter defaultCenter]addObserverForName: //...
是的,可能存在与调用 addObserverForName:
相关的内存管理问题。正如我解释的 in my book:
调用
addObserverForName:object:queue:usingBlock:
返回的观察者令牌由通知中心保留,直到您注销它。观察者令牌也可能会在整个区块中保留您。如果是这样,那么直到您从通知中心取消注册观察者令牌,通知中心才会保留您。这意味着您将泄漏,直到您注销。但是你不能在
dealloc
的通知中心注销,因为只要你注册了dealloc
就不会被调用此外,如果你还保留观察者令牌,那么如果观察者令牌正在保留你,你手上就有一个保留周期。
您可能想阅读我书中的其余讨论以获取实际示例和解决方案。