gpt4 book ai didi

iOS 正确使用 @weakify(self) 和 @strongify(self)

转载 作者:IT老高 更新时间:2023-10-28 11:41:43 28 4
gpt4 key购买 nike

我开始将 libextobjc (https://github.com/jspahrsummers/libextobjc) 集成到我的 iOS 应用程序中,主要是为了利用 EXTScope 的 @strongify@weakify,但有几个问题在继续深入流程之前。

这是一个故意过于复杂的例子,试图弄清楚如何处理这个问题:

- (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],我不需要使用 strong 做任何事情/weak 因为请求 block 本身没有保留完成 block ,所以那里的保留周期没有问题。在上面的代码示例中,我认为 #5 是保留周期不是问题的情况。

主要关注的是所有将 block 作为属性/初始化参数的对象,它们在内部保持 block 属性。在 objectWithCompletionHandler 方法中,其中 someObject 将 completionHandler block 作为实例变量保存,那里有多个对 self 的引用,我知道这会导致泄漏。我的主要问题是在这种情况下,您需要如何处理 weakifystrongify 以使其“更安全”?一个@weakify 和@strongify 调用是否就足够了,如下所示:

- (void)someMethod {
@weakify (self);

_someObjectInstanceVar = [Object objectWithCompletionHandler:^{
@strongify(self);
...
}

上面的 @strongify(self) 引用是否足以用于 self 引用 #1、2、3 和 4,还是我必须(并且它甚至可以工作)获得一个在 sendAWithID 方法和嵌套的 reloadData 中使用的新的弱/强引用?

编辑:修复代码以使问题更有意义并修复一些语法错误。

最佳答案

@strongify 的工作原理

@strongify 被调用后,self 将有一个不同的指针地址 inside block 而不是 outside block 。这是因为 @strongify 每次都声明一个名为 self 的新局部变量。 (这就是它抑制 -Wshadow 警告的原因,它会“在局部变量遮蔽另一个局部变量时发出警告。”)值得阅读和理解 the implementation of these functions .因此,即使名称相同,也要将它们视为单独的 strong 引用。

在代码中使用 @strongify

假设(这是不正确的)每次使用 block 都会创建一个引用循环,您可以:

- (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 将引用本地堆栈变量。当定义它们的范围结束时,它们通常会被销毁(只要您不将它们存储到属性或在嵌套 block 中使用它们)。所以根据你展示的代码,你只需要在 //self reference #1 之后。

另见

阅读unit test covering @weakify and @strongify将有助于阐明这些函数的正确用法。

关于iOS 正确使用 @weakify(self) 和 @strongify(self),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28305356/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com