IOS 5编程 内存管理 ARC技术概述

原文:http://blog.youkuaiyun.com/nicktang/article/details/6792972

Automatic Reference Counting (ARC) 是一个编译期的技术,利用此技术可以简化Objective-C编程在内存管理方面的工作量。
这里我把此技术翻译为自动内存计数器管理技术,下图是使用和不使用此技术的Objective-C代码的区别。
[img]http://hi.youkuaiyun.com/attachment/201109/20/0_13164884049231.gif[/img]
ARC技术是随着XCode4.2一起发布的,在缺省工程模板中,你可以指定你的工程是否支持ARC技术,如果你不指定工程支持ARC技术,在代码中你必须使用管理内存的代码来管理内存。

概述
自动计数(ARC)是一个编译期间工作的能够帮你管理内存的技术,通过它,程序人员可以不需要在内存的retain,释放等方面花费精力。
ARC在编译期间为每个Objective-C指针变量添加合适的retain, release, autorelease等函数,保存每个变量的生存周期控制在合理的范围内,以期实现代码上的自动内存管理。
In order for the compiler to generate correct code, ARC imposes some restrictions on the methods you can use, and on how you use toll-free bridging (see “Toll-Free Bridged Types”); ARC also introduces new lifetime qualifiers for object references and declared properties.
你可以使用编译标记-fobjc-arc来让你的工程支持ARC。ARC在Xcode4.2中引入,在Mac OS X v10.6,v10.7 (64位应用),iOS 4,iOS 5中支持,Xcode4.1中不支持这个技术.
如果你现在的工程不支持ARC技术,你可以通过一个自动转换工具来转换你的工程(工具在Edit->Convert menu),这个工具会自动所有工程中手动管理内存的点转换成合适自动方式的(比如移除retain, release等)。这个工具会转换工程中所有的文件。当然你可以转换单个文件。
ARC提供自动内存管理的功能
ARC使得你不需要再思考何时使用retain,release,autorelease这样的函数来管理内存,它提供了自动评估内存生存期的功能,并且在编译期间自动加入合适的管理内存的方法。编译器也会自动生成dealloc函数。一般情况下,通过ARC技术,你可以不顾传统方式的内存管理方式,但是深入了解传统的内存管理是十分有必要的。
下面是一个person类的一个声明和实现,它使用了ARC技术。
@interface Person : NSObject
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *yearOfBirth;
@property (nonatomic, strong) Person *spouse;
@end

@implementation Person
@synthesize firstName, lastName, yearOfBirth, spouse;
@end

(有关strong的帮助,请参考 “ARC Introduces New Lifetime Qualifiers.”)
使用ARC,你可以象下面的方式实现contrived函数:
- (void)contrived {
Person *aPerson = [[Person alloc] init];
[aPerson setFirstName:@"William"];
[aPerson setLastName:@"Dudney"];
[aPerson:setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];
NSLog(@"aPerson: %@", aPerson);
}

ARC管理内存,所以这里你不用担心aPerson和NSNumber的临时变量会造成内存泄漏。
你还可以象下面的方式来实现Person类中的takeLastNameFrom:方法,
- (void)takeLastNameFrom:(Person *)person {
NSString *oldLastname = [self lastName];
[self setLastName:[person lastName]];
NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);
}

ARC可以保证在NSLog调用的时候,oldLastname还存在于内存中。
ARC中的新规则
为了ARC能顺利工作,特增加如下规则,这些规则可能是为了更健壮的内存管理,也有可能为了更好的使用体验,也有可能是简化代码的编写,不论如何,请不要违反下面的规则,如果违反,将会得到一个编译期错误。
下面的这些函数:dealloc,retain, release, retainCount, autorelease。禁止任何形式调用和实现(dealloc可能会被实现),包括使用@selector(retain), @selector(release)等的隐含调用。
你可能会实现一个和内存管理没有关系的dealloc,譬如只是为了调用[systemClassInstance setDelegate:nil] ,但是请不要调用[super dealloc] ,因为编译器会自动处理这些事情。
你不可以使用NSAllocateObject或者NSDeallocateObject.
使用alloc申请一块内存后,其他的都可以交给运行期的自动管理了。
不能在C语言中的结构中使用Objective-c中的类的指针。
请使用类类管理数据。
不能使用NSAutoreleasePool.
作为替代,@autoreleasepool被引入,你可以使用这个效率更高的关键词。
不能使用memory zones.
NSZone不再需要—本来这个类已经被现代Objective-c废弃。
ARC在函数和便利变量命名上也有一些新的规定
禁止以new开头的属性变量命名。
ARC Introduces New Lifetime Qualifiers
ARC introduces several new lifetime qualifiers for objects, and zeroing weak references. A weak reference does not extend the lifetime of the object it points to. A zeroing weak reference automatically becomes nil if the object it points to is deallocated.
You should take advantage of these qualifiers to manage the object graphs in your program. In particular, ARC does not guard against strong reference cycles (previously known as retain cycles—see “Practical Memory Management”). Judicious use of weak relationships will help to ensure you don’t create cycles.
属性变量修饰符

weak和strong两个修饰符是新引进的,使用例子如下:
// 下面的作用和: @property(retain) MyClass *myObject;相同
@property(strong) MyClass *myObject;

// 下面的作用和"@property(assign) MyClass *myObject;"相识
// 不同的地方在于,如果MyClass的实例析构后,这个属性变量的值变成nil,而不是一个野指针,

@property(weak) MyClass *myObject;

Variable Qualifiers

You use the following lifetime qualifiers for variables just like you would, say, const.
__strong
__weak
__unsafe_unretained
__autoreleasing

__strong is the default. __weak specifies a zeroing weak reference to an object. __unsafe_unretained specifies weak reference to an object that is not zeroing—if the object it references is deallocated, the pointer is left dangling. You use__autoreleasing to denote arguments that are passed by reference (id *) and are autoreleased on return.
Take care when using __weak variables on the stack. Consider the following example:
NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
NSLog(@"string: %@", string);

Although string is used after the initial assignment, there is no other strong reference to the string object at the time of assignment; it is therefore immediately deallocated. The log statement shows that string has a null value.
You also need to take care with objects passed by reference. The following code will work:
NSError *error = nil;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
// Report the error.
// ...

However, the error declaration is implicitly:
NSError * __strong e = nil;
and the method declaration would typically be:
-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
The compiler therefore rewrites the code:
NSError __strong *error = nil;
NSError __autoreleasing *tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
// Report the error.
// ...

The mismatch between the local variable declaration (__strong) and the parameter (__autoreleasing) causes the compiler to create the temporary variable. You can get the original pointer by declaring the parameter id __strong * when you take the address of a __strong variable. Alternatively you can declare the variable as __autoreleasing.
Use Lifetime Qualifiers to Avoid Strong Reference Cycles

You can use lifetime qualifiers to avoid strong reference cycles. For example, typically if you have a graph of objects arranged in a parent-child hierarchy and parents need to refer to their children and vice versa, then you make the parent-to-child relationship strong and the child-to-parent relationship weak. Other situations may be more subtle, particularly when they involve block objects.
In manual reference counting mode, __block id x; has the effect of not retaining x. In ARC mode, __block id x; defaults to retaining x (just like all other values). To get the manual reference counting mode behavior under ARC, you could use__unsafe_unretained __block id x;. As the name __unsafe_unretained implies, however, having a non-retained variable is dangerous (because it can dangle) and is therefore discouraged. Two better options are to either use __weak (if you don’t need to support iOS 4 or OS X v10.6), or set the __block value to nil to break the retain cycle.
The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];

As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
__block MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil;
};

Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
__weak MyViewController *weakMyViewController = myController;
myController.completionHandler = ^(NSInteger result) {
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
};

For non-trivial cycles, however, you should use:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
__weak MyViewController *weakMyController = myController;
myController.completionHandler = ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
// ...
[strongMyController dismissViewControllerAnimated:YES completion:nil];
// ...
}
else {
// Probably nothing...
}
};

In some cases you can use __unsafe_unretained if the class isn’t __weak compatible. This can, however, become impractical for nontrivial cycles because it can be hard or impossible to validate that the __unsafe_unretained pointer is still valid and still points to the same object in question.
自动释放池
使用ARC,你不能使用NSAutoReleasePool类来管理自动释放池了,作为替代,ARC使用一个新的语法结构:
@autoreleasepool {
// Code, such as a loop that creates a large number of temporary objects.
}

编译器根据工程是否使用ARC,来决定这个语法结构最终呈现方式,这个语法结构使用了一种比NSAutoReleasePool更高效的方式。
Outlets
The patterns for declaring outlets in iOS and OS X change with ARC and become consistent across both platforms. The pattern you should typically adopt is: outlets should be weak, except for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be strong.
Outlets that you create should will therefore generally be weak by default:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
For example:
@interface MyFilesOwnerClass : SuperClass

@property (weak) IBOutlet MyView *viewContainerSubview;
@property (strong) IBOutlet MyOtherClass *topLevelObject;
@end

In cases where you cannot create a weak reference to an instance of a particular class (such as NSTextView), you should use assign rather than weak:
@property (assign) IBOutlet NSTextView *textView;

This pattern extends to references from a container view to its subviews where you have to consider the internal consistency of your object graph. For example, in the case of a table view cell, outlets to specific subviews should again typically beweak. If a table view contains an image view and a text view, then these remain valid so long as they are subviews of the table view cell itself.
Outlets should be changed to strong when the outlet should be considered to own the referenced object:
As indicated previously, this often the case with File’s Owner: top level objects in a nib file are frequently considered to be owned by the File’s Owner.
You may in some situations need an object from a nib file to exist outside of its original container. For example, you might have an outlet for a view that can be temporarily removed from its initial view hierarchy and must therefore be maintained independently.
其他的新功能
使用ARC技术,可以使得在栈上分配的指针隐式的初始化为nil,比如
- (void)myMethod {
NSString *name;
NSLog(@"name: %@", name);
}

上面的代码会Log出来一个null,不会象不使用ARC技术的时候使得程序崩溃。
[VCS]VCS checkpoint简介以及其在SoC验证加速中的作用 VCS checkpoint是Synopsys VCS提供的快照/恢复机制,可显著加速SoC验证。其核心是在仿真关键节点(如完成初始化后)保存系统状态,后续测试可直接从该点恢复,避免重复执行冗长的初始化阶段(如boot、DDR训练等)。该技术特别适用于多测试用例共享同一初始状态的场景,通过分离初始化与功能验证流程,可提升回归效率3-5倍。需注意处理DPI-C状态同步、版本管理及存储优化等问题,结合UVM和自动化脚本可实现更高效的验证流程。典型应用可节省数百万cycle的重复仿真时间。 阅读详情

相关推荐

UOS的ARM机编译QT5.14.2记录

我需要的qt版本是Qt5.14.2,所以选择编译Qt5.14.2源码;几个月前尝试了编译一次,当时编译过程中出现了报错,当时时间很紧最后安装的默认版本来使用,最近有时间重新进行了一次编译,历经3个星期(4G的内存)终于解决了各种坑,编译成功了,现在将编译过程中遇见的一些坑记录一下,方便日后能记得这一次可恶的编译过程,如有描述欠缺的地方,还希望各位大佬给点意见指导指导🙏。

NiF693zzz的博客 1617

iOS 5编程 内存管理 ARC技术概述

Automatic Reference Counting (ARC) 是一个编译期的技术,利用此技术可以简化Objective-C编程在内存管理方面的工作量。 这里我把此技术翻译为自动内存计数器管理技术,下图是使用和不使用此技术的Objective-C代码的区别。 ARC技术是随着XCode4.2一起发布的,在缺省工程模板中,你可以指定你的工程是否支持ARC技术,如果你不指定工程...

dongjing9625的博客 164

U盘安装单系统ubuntu10.04之全过程&拔掉U盘后系统无法启动

借助U盘把电脑装成ubuntu单系统之过程记录,以及遇到拔掉U盘后系统无法启动问题,电脑就显示: Non-System disk or disk error, replace and strike any key when ready

CXHPLY的专栏 8679

IOS 5编程 内存管理 ARC技术概述 .

ARC(Automatic Reference Counting )技术概述 此文章由Tom翻译,首发于csdn的blog,任何人都可以转发,但是请保留原始链接和翻译者得名字。多谢! Automatic Reference Counting (ARC) 是一个编译期的技术,利用此技术可以简化Objective-C编程在内存管理方面的工作量。 这里我把此技术翻译为自动内存计

在路上 826

pgAdmin4备份恢复实战:从安装到避坑指南

本文提供了一份详尽的pgAdmin4备份恢复实战指南,涵盖从安装配置到执行备份恢复的全流程。针对Windows环境下的浏览器兼容性、二进制路径配置等常见问题,给出了具体解决方案。重点强调了使用pgAdmin4进行备份恢复的可靠性,特别是在处理包含PostGIS等扩展的数据库时,能有效避免数据类型和权限错误,确保数据迁移的完整性与安全性。

weixin_29266007的博客 439

Python自动化测试全套教程-第一天(python、pycharm开发环境的安装与配置(图文超级详细);附安装包)

本文介绍了Python开发环境的完整安装配置流程。主要内容包括:1) Python解释器的下载安装与版本检测方法;2) PyCharm IDE的下载安装步骤,包括专业版和社区版的选择;3) PyCharm的基础配置和项目创建方法;4) 开发环境的基本构造说明。文章提供了两种获取安装包的方式(官网下载和文章附件),并详细说明了解释器卸载、安装过程中的注意事项,以及如何验证环境配置成功。特别强调了PyCharm安装时的路径选择和虚拟环境的创建方法,为Python初学者提供了完整的开发环境搭建指南。

kiwi_king的博客 2035

LLM Agent控制PLC:从持续稳定到安全边界,工业自动化落地关键

大语言模型(LLM)与工业自动化的融合正成为智能运维的重要方向,而AI Agent不再局限于文本问答,开始通过工具调用直接操作PLC设备。其核心原理是将自然语言意图转化为结构化的函数调用,经由中间层完成协议适配、参数校验与状态跟踪,从而实现设备控制。该技术的价值在于降低工程师运维门槛,提升故障诊断与参数查询效率,并逐步应用于产线监控、操作建议等低风险场景。然而,真实工业环境充满不确定性,设备超时、异常返回、顺序约束等问题频繁出现,这要求Agent具备持续稳定性与安全边界意识。PLCBench基准的出现,正是

weixin_33892359的博客 308

无源定位之时差估计的精确时差估计算法(ETDE)及MATLAB实现程序

时差估计算法之精确时差估计(ETDE)欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想

伊谢尔伦的林中小路 4255

Docker环境下Doris存算分离架构部署与验证实战

存算分离是一种将数据存储与计算资源解耦的架构模式,其核心原理是计算节点无状态化,数据统一存放于S3兼容对象存储,从而实现弹性扩缩容。在Docker容器环境中,通过MinIO提供S3兼容存储、MS管理元数据映射、FE负责查询调度、BE作为纯计算节点,可以快速搭建存算分离验证环境。该方案适用于版本验证、架构演示与团队培训等场景,能有效降低环境搭建成本。本文围绕Docker Compose编排,详细讲解Doris存算分离集群的配置、启动顺序、常见故障排查与性能调优,帮助读者掌握存算分离架构的工程实践要点。

weixin_34175509的博客 347

【计算机视觉学习03】全景图像拼接

文章目录一、基本原理1.1 图像拼接的几何原理1.2 直线,圆,复杂曲线方程拟合1.3 RANSAC算法1.4 APAP算法1.5 寻找最佳拼接缝(Seam Finding)1.5.1 最大流问题1.5.2 最大流问题的增广链算法1.5.3 最大流最小割定理二、 图像拼接具体实现2.1 代码2.2 运行结果 一、基本原理 将两幅或多幅具有重叠区域的图像,通过特征匹配将具有相同的特征点(SIFT特征点)的图像拼接在一起,将来自多个不同视角拍摄的图像变换到同一视角下,拼接成一张宽视野图像。 图像拼接基础流程

一个正在努力学习的iter 7787

Java实现双色球&大乐透随机选号算法——原理详解与代码实战

掌握核心语法:集合操作、随机数生成、排序。贴近实际场景:将编程知识应用于生活问题的解决。

wangchl0932的博客 4974

IOS 5编程 内存管理 ARC技术概述 常见问题解答

ARC的机制是什么?它在那里放入retain/release函数调用? 请停止思考这些问题,把更多的精力放在下面的问题上,比如你的程序逻辑,对象的强,弱引用,对象的所属关系,可能的循环引用等问题上。 我还需要为我的类写一个dealloc函数么? 可能。 因为ARC并不自动调用malloc/free,并不自动管理像核心功能对象、文件描述符等的生命周期,所以你仍然需要在dealloc中释放它们

volcan1987的专栏 1811

大疆A型板使用经验分享(四)—— PWM和舵机SG996的控制

一. j

weixin_43361652的博客 3879
上一篇: 获取iOS设备当前ip地址
下一篇: 5个开源库的JSON解析速度测试
iteye_3205
博客等级 码龄8年 0粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值