【问题标题】:iOS: How to remove object from memory with ARC enabled?iOS:如何在启用 ARC 的情况下从内存中删除对象?
【发布时间】:2011-10-03 06:23:01
【问题描述】:

我正在使用 iOS 5 SDK 开发一个 iOS 应用程序,自动引用计数已启用。但是我有一个正在大量创建的特定对象,必须在一秒钟后释放,否则设备会变得非常慢。看起来它们没有发布,因为设备非常慢。有没有办法在启用 ARC 时手动释放对象?

编辑:我的代码,每秒调用 200 次以产生火花。它们会在 0.8 秒后淡出,所以在那之后它们就没有用了。

    int xanimationdiff = arc4random() % 30;
    int yanimationdiff = arc4random() % 30;
    if (arc4random()%2 == 0) {
        xanimationdiff = xanimationdiff * -1;
    }
    if (arc4random()%2 == 0) {
        yanimationdiff = yanimationdiff * -1;
    }

    Sparkle *newSparkle = [[Sparkle alloc] initWithFrame:CGRectMake(20 + arc4random() % 280, 20, 10, 10)];
    //[newSparkle setTransform:CGAffineTransformMakeRotation(arc4random() * (M_PI * 360 / 180))]; //Rotatie instellen (was niet mooi, net sneeuw)
    [self.view addSubview:newSparkle];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.8];
    [newSparkle setFrame:CGRectMake(newSparkle.frame.origin.x - xanimationdiff, newSparkle.frame.origin.y - yanimationdiff, newSparkle.frame.size.width, newSparkle.frame.size.height)];
    newSparkle.alpha = 0;
    [UIView commitAnimations];

闪闪发光的对象代码:

#import "Sparkle.h"

@implementation Sparkle

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"sparkle.png"]]];
    }
    return self;
}

@end

【问题讨论】:

    标签: ios automatic-ref-counting


    【解决方案1】:
    Object* myObject = [[Object alloc] init];     
    myObject = nil; // poof...
    

    编辑:您无法直接控制何时释放对象,但您可以间接导致它发生。如何?记住 ARC 究竟做了什么。与人类编码约定不同,ARC 会解析您的代码并在对象可以发布时插入发布语句。这会立即为新分配释放内存,这非常棒/必要。 意思是,将一个对象设置为 nil,或者只是允许一个变量超出范围......导致 0 RETAIN COUNT 的东西迫使 ARC 将其释放调用放在那里。 它必须......因为否则它会泄漏。

    【讨论】:

    • 并非在所有情况下都是如此。如果您没有打开某些编译器优化(通常是在您未在发布模式下运行时),ARC 不会立即释放对象。
    • 设置为 nil 通常是在一个对象被释放后完成的——以避免悬空指针。设置为 nil 怎么会导致最终导致 dealloc 的释放?看起来像因果颠倒。
    • 部分正确:“您无法直接控制何时释放对象”。您可以使用autorelease pools 来控制它。 Autorelease Pool BlocksRun loops and Autorelease Pools
    【解决方案2】:

    只需用 @autoreleasepool { ... } 语句将要调用 200 次的代码部分包围起来。这将导致内存立即被释放,而不是等待控件一路将事件链备份到顶级自动释放池。

    【讨论】:

      【解决方案3】:

      我找到了答案,实际上真的很愚蠢。我没有从超级视图中删除火花。现在我用计时器在 0.8 秒后删除它们,它再次表现出色:)

      【讨论】:

      • 太棒了——正如您可能猜到的,当您将视图添加到超级视图时,它仍会保留,因此这可能是您问题的根源。很高兴它已修复!
      【解决方案4】:

      使用 ARC,您无法调用 deallocreleaseretain,尽管您仍然可以保留和释放 CoreFoundation 对象(注意:您可以为自己实现 dealloc 方法自定义子类,但不能调用super dealloc)。所以简单的答案是“不”,很遗憾,您在使用 ARC 时无法手动释放对象。

      我会仔细检查你确定它们没有被释放,因为理论上如果你不再引用一个对象,它应该被释放。创建这些对象后,您将如何处理它们?您只是创建它们然后立即销毁它们?

      也许您可以发布您正在使用的代码/属性声明 - 这些是 weakstrong 引用的对象吗?

      【讨论】:

      • 你不能将对象设置为'nil'吗?我很担心,因为我在循环中构建了许多 NSArray 和 Dictionary 对象并将它们添加到全局数组中,所以在那之后我不需要它们。 ARC 如何删除循环中构建的对象?
      • 这不是它的工作原理 - 如果您在 for 循环中创建对象并将它们添加到全局数组中,它们仍将被保留。在从全局数组中移除(即,它们的保留计数为零)之前,它们不能被释放。
      猜你喜欢
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      相关资源
      最近更新 更多