所以我正在阅读如何在实现API时避免在块中捕获自身? 关于内存管理如何在完成块中引用self并且让我思考:以下内容是否会导致保留周期?
伪代码:
[AFnetworking requestGet:@"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){ [self.tableView reloadData]; }];忽略语法问题,self.tableView会导致保留周期吗? 是否有必要做以下事情?
__weak id weakSelf = self; [AFnetworking requestGet:@"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){ [weakSelf.tableView reloadData]; }];或者AFNetworking是否有某种记忆魔法可以阻止这种情况?
编辑Aaron Brager的礼貌
这里没有保留周期。 但是如果你这样做了,在完成块中,你应该将weakSelf转换回强引用,这样它就不会在你的完成块中途被解除分配。
id strongSelf = weakSelf; [strongSelf.tableView reloadData];So I was reading How do I avoid capturing self in blocks when implementing an API? about how memory management works in regards to referencing self within a completion block and that got me thinking: will the following cause a retain cycle?
Pseudocode:
[AFnetworking requestGet:@"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){ [self.tableView reloadData]; }];Ignoring syntax problems, does self.tableView cause a retain cycle? Is it necessary to do the following instead?
__weak id weakSelf = self; [AFnetworking requestGet:@"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){ [weakSelf.tableView reloadData]; }];Or is there some sort of memory magic that AFNetworking does to prevent this?
Edit courtesy of Aaron Brager
Here you don't have a retain cycle. But if you did, in the completion block, you should convert weakSelf back into a strong reference so it won't get deallocated halfway through your completion block.
id strongSelf = weakSelf; [strongSelf.tableView reloadData];最满意答案
当两个或多个对象具有彼此强引用时,会发生保留周期。
在这种情况下,块将具有对self的强引用,但self没有对块的强引用,所以你在这里 没 问题 , 也不需要使用 weakSelf 。
当你有一个保留周期并且需要通过使用weakSelf来打破它的weakSelf是当类具有对块的强引用时,如下例所示:
typedef void (^CompletionCallback)(RequestObj* request, NSError* error); @interface SomeClass() { /// Strong reference to the block CompletionCallback completionBlock; } @end @implementation SomeClass() - (void)someMethod { completionBlock = ^(RequestObj* request, NSError* error) { /// Strong reference to the class [self.tableView reloadData]; }; [AFnetworking requestGet:@"http://www.website.com" completionBlock:completionBlock]; } @end在这个例子中, completionBlock和self都有相互之间的强引用,因此你在这里有一个保留周期,需要打破它。
A retain cycle occurs when two or more objects have strong references to each other.
In this case, the block will have a strong reference to self, but self doesn't have a strong reference to the block, so you are fine here and no need to use weakSelf.
The case when you'll have a retain cycle and need to break it by using the weakSelf is when the class has a strong reference to the block too like in the following example:
typedef void (^CompletionCallback)(RequestObj* request, NSError* error); @interface SomeClass() { /// Strong reference to the block CompletionCallback completionBlock; } @end @implementation SomeClass() - (void)someMethod { completionBlock = ^(RequestObj* request, NSError* error) { /// Strong reference to the class [self.tableView reloadData]; }; [AFnetworking requestGet:@"http://www.website.com" completionBlock:completionBlock]; } @endIn this example, both completionBlock and self have strong references to each other, and therefore you'll have a retain cycle here and need to break it.
更多推荐
发布评论