Objective C 内存管理,包括块、ARC 和非 ARC

2024-04-11

我使用块已经有一段时间了,但我觉得在 ARC 和非 ARC 环境中,我都怀念一些关于内存管理的事情。我觉得更深层次的理解会让我避免很多内存泄漏。

AFNetworking 是我在特定应用程序中对 Blocks 的主要使用。大多数时候,在操作的完成处理程序中,我会执行类似“[self.myArray addObject]”的操作。

在 ARC 和非 ARC 启用环境中,“self”将根据这篇文章来自苹果 http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1.

这意味着每当调用 AFNetworking 网络操作的完成块时, self 都会保留在该块内,并在该块超出范围时释放。我相信这对于 ARC 和非 ARC 都适用。我已经运行了泄漏工具和静态分析器,以便我可以发现任何内存泄漏。没有任何显示。

然而,直到最近我才偶然发现了一个我无法理解的警告。我在这个特定示例中使用 ARC。

我有两个实例变量,分别指示网络操作的完成和失败

@property (nonatomic, readwrite, copy) SFCompletionBlock completionBlock;
@property (nonatomic, readwrite, copy) SFFailureBlock failureBlock;
@synthesize failureBlock = _failureBlock;
@synthesize operation = _operation;

在代码中的某个地方,我这样做:

[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id
                                                    responseObject) {
NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
            _failureBlock(error);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"nothing");
        }];

Xcode 抱怨调用 failureBlock 的行,并显示消息“在该块中强烈捕获“self”可能会导致保留周期”。我相信 Xcode 是对的:failure 块保留 self,并且 self 拥有自己的副本块,因此两者都不会被释放。

但是,我有以下问题/观察结果。

1)如果我将 _failureBlock(error) 更改为“self.failureBlock(error)”(不带引号),编译器将停止抱怨。这是为什么?这是编译器错过的内存泄漏吗?

2) 一般来说,在使用 ARC 和非 ARC 环境中使用块的最佳实践是什么?作为实例变量的块?似乎在 AFNetworking 中的完成和失败块的情况下,这两个块是not实例变量,因此它们可能不属于我上面描述的保留周期的类别。但是,当在 AFNetworking 中使用进度块时,可以采取什么措施来避免像上面那样的保留循环呢?

我很想听听其他人对 ARC 和非 ARC 块的想法以及内存管理的问题/解决方案。我发现这些情况很容易出错,我觉得有必要对此进行一些讨论以澄清问题。

我不知道这是否重要,但我使用带有最新 LLVM 的 Xcode 4.4。


1)如果我将 _failureBlock(error) 更改为“self.failureBlock(error)” (不带引号)编译器停止抱怨。这是为什么?这是 编译器错过的内存泄漏?

两种情况都存在保留周期。如果您的目标是 iOS 5+,则可以传递对 self 的弱引用:

__weak MyClass *weakSelf;
[self.operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSError *error = [NSError errorWithDomain:@"com.test" code:100 userInfo:@{@"description": @"zero results"}];
    if (weakSelf.failureBlock) weakSelf.failureBlock(error);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"nothing");
}];

现在 self 将不会被保留,如果在调用回调之前释放它,则回调是无操作的。但是,当在后台线程上调用回调时,它可能会进行释放,因此这种模式可能会造成偶尔的崩溃。

2)一般来说,在这两种情况下使用块的最佳实践是什么 使用以下块时的 ARC 和非 ARC 启用环境 实例变量?看来在完成和失败的情况下 AFNetworking 中的块,这两个块不是实例变量,因此 它们可能不属于我认为的保留周期类别 如上所述。但是当在 AFNetworking 中使用进度块时, 可以采取什么措施来避免像上面那样的保留循环?

大多数时候,我认为最好不要将块存储在实例变量中 http://twobitlabs.com/2012/05/block-initialization-for-testability-and-reuse/。如果您从类中的方法返回块,您仍然会有一个保留周期,但它只存在于调用该方法的时间到释放块的时间之间。因此,它将阻止您的实例在块执行期间被释放,但保留周期会在块被释放时结束:

-(SFCompletionBlock)completionBlock {
    return ^(AFHTTPRequestOperation *operation , id responseObject ) {
        [self doSomethingWithOperation:operation];
    };
}

[self.operation setCompletionBlockWithSuccess:[self completionBlock]
                                      failure:[self failureBlock]
];
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Objective C 内存管理,包括块、ARC 和非 ARC 的相关文章

随机推荐

  • 在 Visual Studio 中使用 VSCode 扩展

    今天我发现了一个VSCode 扩展 https marketplace visualstudio com items itemName GrapeCity gc excelviewer我非常想在 Visual Studio 2017 专业版
  • REST API 设计中的查找或创建习惯用法?

    假设我们有一个 用户 资源 对 名称 有唯一的约束 您将如何设计 REST API 来处理查找或创建 按名称 用例 我看到以下选项 选项 1 多个请求 client POST user name bob server HTTP 409 or
  • RichTextBox 并在插入符位置插入

    事情是这样的 我有一个 RichTextBox 控件 它工作正常 问题是有一个按钮 插入当前日期时间 它将当前日期时间添加 注入到 RichTextBox 中 用户可以在插入符号指向的任何位置输入日期时间 这涉及复杂的字符串操作之类的东西
  • Python3中的__builtin__模块在哪里?为何更名?

    我很好奇 builtin 模块及其使用方法 但我在Python3中找不到它 为什么被移动 Python 2 7 gt gt gt import builtin gt gt gt Python 3 2 gt gt gt import buil
  • 更新 EF 4.1 中的记录

    我有一个员工对象说 public class Employee public int Id get set public int Name get set public int Address get set other few 10 s
  • 使用 ruby​​ Net:HTTP API 将文件上传到远程 apache 服务器失败并出现 409 冲突

    下面是一个将文件从本地文件系统上传到远程 Apache 服务器的程序 程序以 409 冲突错误结束 有什么建议我做错了什么吗 我在 httpd conf 中打开了 DAV 并授予了所有必要的权限 但我仍然没有运气 如果需要的话我可以发布ht
  • 我们如何在 google puppeteer 的无头 Chrome 中传递身份验证令牌?

    我想在 puppeteer 标头中传递身份验证令牌 JWT 以用于我的应用程序中使用无头 Chrome 的 pdf 视图 我们使用 React 作为我们的前端 UI 使用 puppeteer 我们可以生成 pdf 但是 pdf 的链接我们需
  • ios中文字符编码问题

    我有一个应用程序支持四种语言 当我当时使用中文用户名登录时 它会显示这样的响应 0 41 intid 41 1 u8a00 u3046 varfirstname u8a00 u3046 2 u8a00 u3046 varlastname u
  • 针对自定义表单类型使用 sonata_type_collection 而不是与另一个实体的属性/关系

    是否可以使用sonata type collection针对自定义表单类型而不是与另一个实体的属性 关系 像这样的事情 formMapper gt add foo sonata type collection array type gt n
  • 我如何使用 php api 读取 gmail 主题?

    在女巫模式下 可以使用 php api 读取电子邮件主题吗 我做这个代码 Get the API client and construct the service object client getClient service new Go
  • 从 SVG 中删除“填充”?

    I have a SVG graphic that draws a circle When I give it a background color with CSS I expected it to show up only in the
  • 轻量级、基于 PHP 的布局框架...知道吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个轻量级的 基于 PHP 的布局框架 就像 Zend Framework 如何使用布局一样 我想创建一个布局模板并仅包含必要页
  • 在 Java 中使用 AudioPlayer

    在我的 swing 应用程序中 我使用一个类在单击鼠标时播放声音 我遇到的问题是 当我调用班级时 声音会播放一次 而当突然单击另一个按钮时 它不会播放声音 我尝试在代码中给出延迟 但 id 仍然无法按我的预期工作 和线程有关系吗 我不擅长线
  • 为什么 Orion 订阅不能按我的意愿工作?

    我在 orion 1 2 1 中有以下订阅 curl include header Content Type application json request POST data binary description subscriptio
  • 正则表达式解析任意深度的函数

    我正在为其中包含的函数解析一种简单的语言 Excel 公式 函数名称必须以任意字母开头 后跟任意数量的字母 数字 并以左括号结尾 中间没有空格 例如MyFunc 该函数可以包含任何参数 包括其他函数 并且必须以右括号结尾 当然 括号内的数学
  • 如何更改多个提交按钮的值? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我如何重命名所有submit当我点击按钮时 我需要脚本 该脚本会改变submit按钮的值类似于所有按钮的 正在加载 我需要完整的 jQ
  • Visual Studio 2013 和 libpng [重复]

    这个问题在这里已经有答案了 我正在尝试使用 VS2013 在 C 中使用 libpng 编写一个简单的 PNG 文件 我从 Nuget 安装了 libpng 并包含了 png h 但无法编译 我得到这个作为我的输出 1 gt main ob
  • 在 php 文件中包含网站

    您好 我正在尝试将另一个网站的网页链接包含到我的网站中 我怎样才能做到这一点 i tried 但在此语句之后所有命令都不会加载 我想将另一个网页直接包含到我的主页中 我的主页完全是用php设计的 但是另外一个是html或者php 我也尝试过
  • 在 .NET Core csproj 文件中更改为 (复数)时出错

    我正在关注 Pluralsight 上的一个关于让 MSTest 项目同时针对 net core 2 2 和 NET 4 7 2 的教程 这需要转到我的测试项目的 csproj 文件并对其进行编辑 以便以下内容
  • Objective C 内存管理,包括块、ARC 和非 ARC

    我使用块已经有一段时间了 但我觉得在 ARC 和非 ARC 环境中 我都怀念一些关于内存管理的事情 我觉得更深层次的理解会让我避免很多内存泄漏 AFNetworking 是我在特定应用程序中对 Blocks 的主要使用 大多数时候 在操作的