ARC并释放内存

时间:2011-12-19 17:40:19

标签: iphone objective-c automatic-ref-counting

我在线阅读了很多文章,我对ARC感到有点困惑。我将在下面列出我的问题,请帮我回答。

1。)关键字strong做什么(在@property (nonatomic, strong) …中)?

2。)我们不再需要releaseautorelease我们alloc了,因为我得到一个警告说我不需要。 (我不在我的Mac上,所以我无法复制我收到的警告。)

3.)我在Xcode 4.2中找不到Leaks工具。它去了哪里?或者我们不必再检查泄漏了吗?

4。)使用Xcode 4.2创建项目时,我点击了“启用ARC”,那么我的程序是否可以在iOS 3上运行? (我认为ARC仅支持iOS 4及更高版本。)

3 个答案:

答案 0 :(得分:7)

  1. strongretain的ARC模拟(ARC下没有retain)。这意味着属性值将由定义@property的类保持,并在重新分配或释放时释放。 (请注意,在ARC下,无需在dealloc中释放或取消属性)。

  2. ARC的重点在于编译器处理retain / release例程,因此不需要手动内存管理方法。

  3. 您可以通过运行个人资料(Product -> Profile菜单)并选择泄漏工具来检查是否有泄漏。可以使用循环引用或CoreFoundation代码引入泄漏(ARC不适用于CoreFoundation)。此外,如果您混合ARC和非ARC代码,后者可能是泄漏的来源。

  4. 从iOS 4.0开始,操作系统支持ARC(虽然需要iOS 5 SDK)。 4.0和5.0 ARC支持之间的关键区别是weak属性说明符的可用性。当引用的__weak值被释放时,弱属性(strong变量)将自动无效。 4.0中没有weak属性,因此应该使用__unsafe_unretained说明符(它与assign说明符类似,它不保留值并且可以指向已经释放的值,所以这很危险。)

  5. 以下是ARC的一个很好的解释: Everything you need to know about automatic reference counting

答案 1 :(得分:6)

  1. Strong相当于ARC中的retain。它表示所有权:What does the "strong" keyword do

  2. 不,那已经为你完成了。 ARC自动在(编译)代码中插入这些语句。这是它的主要工作。但是,根据Abizern的评论,这仅适用于您的对象和Cocoa对象。如果您正在使用Core Foundation(CF*)类,那么您必须阅读有关__bridge系列演员表的内容。 You might start reading here.

  3. 它在仪器中。根据iHunter的回答,Cmd + I或Product-> Profile,然后选择Leaks。特别重要的是(2)。

  4. 它不起作用。

答案 2 :(得分:2)

嗯,已经有三个答案涵盖了主要内容,所以我将专注于这里的一个细节,这还没有提到:

  

3.)我在Xcode 4.2中找不到Leaks工具。它去了哪里? 或者我们不能再检查泄漏了吗?

是的,我们仍然需要检查泄漏:

ARC不是垃圾收集,它是自动保留/释放。

因此,它仍然可能 - 事实上,很容易造成泄漏!

考虑以下示例:

@class Puppet;
@protocol PuppetDelegate : <NSObject>
- (void)puppetDidTwistStrings:(Puppet *)puppet;
@end

@interface Puppet : NSObject {
    id <PuppetDelegate> delegate_;
}

- (id)initWithPuppetDelegate:(id <PuppetDelegate>)delegate;
- (void)unravelStrings;

@end

@implementation Puppet
- (id)initWithPuppetDelegate:delegate
{
    if (!(self = [super init])) return nil;

    delegate_ = delegate;

    return self;
}

// assume some implementation for unravel strings

@end

@interface MasterOfPuppets : NSObject <PuppetDelegate> {
    NSMutableArray *puppets_;
}

- (void)puppetDidTwistStrings:(Puppet *)puppet;
- (void)bringOutAPuppet;

@end

@implementation
- (id)init
{
     if (!(self = [super init])) return nil;

     puppets_ = [[NSMutableArray alloc] init];

     return self;
}

- (void)bringOutAPuppet
{
    Puppet *newPuppet = [[Puppet alloc] initWithPuppetDelegate:self];
    [puppets_ addObject:newPuppet];
}

- (void)puppetDidTwistStrings:(Puppet *)puppet
{
    BOOL isOurPuppet = [puppets_ containsObject:puppet];
    if (!isOurPuppet) return;

    [puppet unravelStrings];
}
@end

这个例子(不可否认)有点愚蠢,但是这段代码会泄漏,ARC不会帮你解决这个问题,而垃圾收集则会:

  • MasterOfPuppets可以有很多木偶,他存储在一个实例变量中 - 到目前为止一直很好。
  • Puppet有一个委托,它会告知它的字符串是否纠缠在一起 - 在这里开始。

在非ARC代码中,实例变量只是一个指定的指针,ARC假定如果你在变量中存放某些东西,你想要依赖它,它将retain值除非告诉它不要。

所以你在这里有一个经典的保留周期,ARC不会让你免于那些。

这似乎是一个人为的,牵强附会的例子,但事实并非如此:我在委托关系中已经看到了这一点。

(顺便说一句,解决方案非常简单:将Puppet的{​​{1}}实例变量声明为delegate_,一切正常。