iOS正确使用@weakify(self)和@strongify(self) [英] iOS Proper Use of @weakify(self) and @strongify(self)
问题描述
我开始将libextobjc( https://github.com/jspahrsummers/libextobjc )整合到我的iOS应用程序中利用EXTScope的 @strongify
和 @weakify
,但在深入了解该过程之前有几个问题。
I'm starting to integrate libextobjc (https://github.com/jspahrsummers/libextobjc) into my iOS application primarily to take advantage of EXTScope's @strongify
and @weakify
, but have a few questions before proceeding too deep into the process.
这是一个故意过于复杂的例子,试图解决如何处理这个问题:
Here's an example that's intentionally overly-complicated to try to suss out how to handle this:
- (void)someMethod {
if (self.someBOOL) {
_someObjectInstanceVar = [Object objectWithCompletionHandler:^{
// self reference #1
if (self.someProperty) {
// self reference #2
[[Async HTTPRequest] sendAWithID:self.property.id completionHandler:^(void (^)(NewObject *newObject) {
// self reference #3
[self showViewWithObject:newObject handler:^{
// self reference #4
[self reloadData];
}];
}];
}
}];
else {
[[Async HTTPRequest] sendBWithID:self.property.id completionHandler:^{
// self reference #5
[self reloadData];
}];
}
}
我的理解是,如果我想做任何事情,比如一个异步HTTP请求,并在完成处理程序引用self中,如 [self reloadData]
,我不需要对强/弱做任何事情,因为请求块本身不是保留完成块,因此保留周期没有问题。在上面的代码示例中,我认为#5 是一个保留周期不是问题的情况。
My understanding is that if I want to do anything like an async HTTP request, and inside the completion handler reference self, like [self reloadData]
, I don't need to do anything with strong/weak as the request block itself isn't retaining the completion block, so there's no problems with retain cycles there. In the above code example, I think #5 is a case where a retain cycles isn't an issue.
主要关注的是所有将块作为属性/ init参数的对象,内部保留在块属性中。在 objectWithCompletionHandler
方法中, someObject
作为实例变量保存在completionHandler块中,有多个对self的引用我知道会导致泄漏。我的主要问题是在这种情况下,您需要如何处理弱化
和 strongify
以使其更安全 ?一个@weakify和@strongify调用是否足够,如下所示:
The main concern are all of the objects that take a block as a property/init param, that are internally holding onto the block properties. Inside the objectWithCompletionHandler
method, where someObject
holds onto the completionHandler block as an instance variable, there are multiple references to self there that I do know would cause a leak. My main question is in such a case, how would you need to handle weakify
and strongify
to make it "safer"? Would one @weakify and @strongify call each be sufficient, like the following:
- (void)someMethod {
@weakify (self);
_someObjectInstanceVar = [Object objectWithCompletionHandler:^{
@strongify(self);
...
}
以上 @strongify(self)
引用足以用于自引用#1,2,3和4,或者我必须(甚至可以工作)获得一个新的弱/强引用在 sendAWithID
方法内使用,嵌套 reloadData
?
Would the above @strongify(self)
reference be sufficient to use for self references #1, 2, 3, and 4, or do I have to (and would it even work) get a new weak/strong reference to use inside the sendAWithID
method and the nested reloadData
?
编辑:固定代码让问题更有意义并修复一些语法错误。
Fixed code to have question make more sense and fix some syntax errors.
推荐答案
如何 @ strongify
有效
调用 @strongify
后, self
块中 块内的指针地址不同于块 块。那是因为 @strongify
每次都声明一个名为 self
的新局部变量。 (这就是它抑制 -Wshadow
警告的原因,它会在局部变量影响另一个局部变量时发出警告。)值得阅读和理解这些功能的实现。因此,即使名称相同,也将它们视为单独的强
引用。
How @strongify
works
After @strongify
is called, self
will have a different pointer address inside the block than it will outside the block. That's because @strongify
declares a new local variable called self
each time. (This is why it suppresses the -Wshadow
warning, which will "warn whenever a local variable shadows another local variable.") It's worth reading and understanding the implementation of these functions. So even though the names are the same, treat them as separate strong
references.
预先假定(这不是真的)每次使用一个块都会创建一个参考周期,你可以:
Presupposing (which is not true) that each use of a block would create a reference cycle, you could:
- (void)someMethod {
if (self.someBOOL) {
@weakify(self);
_someObjectInstanceVar = [Object objectWithCompletionHandler:^{
@strongify(self);
// self reference #1
if (self.someProperty) {
@weakify(self);
// self reference #2
[[Async HTTPRequest] sendAWithID:self.property.id completionHandler:^(void (^)(NewObject *newObject) {
@strongify(self);
// self reference #3
@weakify(self);
[self showViewWithObject:newObject handler:^{
// self reference #4
@strongify(self);
[self reloadData];
}];
}];
}
}];
// etc…
}
但是,请记住第一次使用之后的 @strongify
, self
将引用本地堆栈变量。当它们定义的范围结束时,它们通常会被销毁(只要您不将它们存储到属性或在嵌套块中使用它们。那么基于您的代码显示,你只需要 //自我引用#1
。
However, remember that after your first use of @strongify
, self
will refer to local, stack variables. These will typically get destroyed when the scope in which they're defined ends (as long as you aren't storing them to properties or using them in a nested block). So based on the code you showed, you only need it after // self reference #1
.
阅读单元测试 @weakify
和 @strongify
将有助于澄清这些功能的正确用法。
Reading the unit test covering @weakify
and @strongify
will help clarify the correct usage of these functions.
这篇关于iOS正确使用@weakify(self)和@strongify(self)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!