【问题标题】:Will An Associated Object Be Released Automatically?关联对象会自动释放吗?
【发布时间】:2012-06-01 00:04:14
【问题描述】:

注意:这个其他问题似乎相关,但不是:When does an associated object get released?

我正在向UIView 实例添加第二个描述,如下所示:

- (void) setSecondDescription:(UIView*)view description2:(NSString*)description2 {
    objc_setAssociatedObject (view,&key,description2,OBJC_ASSOCIATION_RETAIN);
}

- (NSString*) secondDescription:(UIView*)view {
    return (id)objc_getAssociatedObject(view, &key);   
}

如果UIView 解除分配,关联的描述 2 会被解除分配吗?有什么办法可以让这种情况自动发生?

【问题讨论】:

    标签: objective-c ios


    【解决方案1】:

    如果您想真正查看整个 dealloc 时间线的描述,请查看 WWDC 2011, Session 322, 36:22。但是,这是基本的概要(我想记住它,所以这是我的一段代码中的实际注释)。

    注意,关联的对象在生命周期结束时被释放。

    // General Information
    // We take advantage of the documented Deallocation Timeline (WWDC 2011, Session 322, 36:22).
    // 1. -release to zero
    //     * Object is now deallocating and will die.
    //     * New __weak references are not allowed, and will get nil.
    //     * [self dealloc] is called
    // 2. Subclass -dealloc
    //     * bottom-most subclass -dealloc is called
    //     * Non-ARC code manually releases iVars
    //     * Walk the super-class chain calling -dealloc
    // 3. NSObject -dealloc
    //     * Simply calls the ObjC runtime object_dispose()
    // 4. object_dispose()
    //     * Call destructors for C++ iVars
    //     * Call -release for ARC iVars
    //     * Erase associated references
    //     * Erase __weak references
    //     * Call free()
    

    【讨论】:

    • +1 这是很棒的东西,乔迪。我可能不得不实际观看会话,因为我无法理解此代码的位置。但这更多的是我对 Obj-C 的组合方式缺乏了解。
    • 当引用计数变为0时,对象开始死亡,执行此代码路径。有一些设置不允许新的弱引用和其他一些东西,然后 dealloc 链开始。当 dealloc 链完成时,即所有实例变量都被销毁(在 ARC 下)。关联的对象只是一个与其他东西一起附加的地图(嗯,它曾经是一个 std::map - 我最近没有看过,但我真的希望他们使用一个小数组关联对象的数量,然后使用映射 - 限制内存消耗)。
    • 这是一条很棒的信息,乔迪,谢谢。顺便补充一下,我发现在 iOS4 中,如果您将关联对象添加到也注册为观察者的对象,则即使该对象确实被释放,关联对象也永远不会被释放。因此,在 iOS4 中将 KVO 与关联对象结合使用会以某种方式打破这个链条。
    【解决方案2】:

    是的。当一个对象被释放时,所有关联的对象(使用RETAINCOPY 关联类型)都会自动释放。

    【讨论】:

      【解决方案3】:

      简而言之,是的 - 当拥有对象被释放时,保留的关联对象被释放。见苹果documentation第一部分

      【讨论】:

      • 我看过那个部分。它在哪里说它被释放了?
      • @Yar 在第一部分(创建关联)的第二句到最后一句中非常清楚:“但是,当数组被释放时(在第 2 点),概述被释放,因此在这种情况下也解除分配。” :)
      【解决方案4】:

      Jody Hagins 的answer 中的第 4 节说“擦除关联的引用”,这并没有明确暗示引用已被释放。所以我使用下面的一段代码(注意没有 ARC)来测试这个。

      @interface AssociatedObjectHelper : NSObject
      @end
      
      @implementation AssociatedObjectHelper
      - (void) dealloc
      {
          NSLog(@"In %s", __FUNCTION__);
          [super dealloc];
      }
      @end
      
      @implementation AppDelegate
      ...
      - (void) testReleaseAssociatedObject
      {
          static const NSString *key = @"testKey123";
          NSObject *ob = [NSObject new];
          AssociatedObjectHelper *assocOb = [AssociatedObjectHelper new];
          objc_setAssociatedObject(ob, key, assocOb, OBJC_ASSOCIATION_RETAIN);
          [assocOb release];
          [ob release];
      }
      

      调用上述代码确实最终会调用 -[AssociatedObjectHelper dealloc],并带有以下堆栈跟踪:

      #0  0x000000010000528f in -[AssociatedObjectHelper dealloc]
      #1  0x00007fff8a0bb89c in objc_object::sidetable_release(bool) ()
      #2  0x00007fff8a0a537f in _object_remove_assocations ()
      #3  0x00007fff8a0a1644 in objc_destructInstance ()
      #4  0x00007fff8a0a1595 in object_dispose ()
      #5  0x00007fff8a0bb89c in objc_object::sidetable_release(bool) ()
      #6  0x000000010000e9b6 in -[AppDelegate testReleaseAssociatedObject]
      

      在 Xcode 7.0.1 上测试

      【讨论】:

        猜你喜欢
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-02
        • 1970-01-01
        • 2011-08-27
        • 2010-11-23
        • 1970-01-01
        相关资源
        最近更新 更多