代码之家  ›  专栏  ›  技术社区  ›  schwa

为什么我不应该在in i t/dealloc中使用目标C 2.0访问器?[关闭]

  •  41
  • schwa  · 技术社区  · 16 年前

    @mmalc's response this question 他说“一般来说你应该 在dealloc(或init)中使用accessor方法。“mmalc为什么这么说?

    我能想到的唯一真正原因是性能和避免@dynamic setter未知的副作用。

    讨论?

    6 回复  |  直到 13 年前
        1
  •  19
  •   Louis Gerbarg    15 年前

    这一切都是关于使用习惯上一致的代码。如果您对所有代码都进行了适当的模式化,那么有一些规则可以保证在init/dealloc中使用访问器是安全的。

    最大的问题是(正如mmalc所说)设置属性默认状态的代码不应该通过访问器,因为它会导致各种各样的棘手问题。catch是init不必设置属性的默认状态。出于许多原因,我一直在转向自初始化的访问器,如下面的简单示例:

    - (NSMutableDictionary *) myMutableDict {
        if (!myMutableDict) {
            myMutableDict = [[NSMutableDictionary alloc] init];
        }
    
        return myMutableDict;
    }
    

    这种类型的属性初始化允许延迟许多实际上不需要的初始化代码。在上述情况下,in it不负责初始化属性状态,并且在in it方法中使用访问器是完全安全的(甚至是必要的)。

    诚然,这确实对代码施加了额外的限制,例如,具有自定义访问器的子类对于超类中的属性必须调用超类访问器,但这些限制与cocoa中常见的各种其他限制并不冲突。

        2
  •  29
  •   Andrew Grant    16 年前

    它基本上是一个最小化潜在错误的指导方针。

    在这种情况下,(可能)您的setter/getter可能无意中对对象的状态做出直接或间接的假设。当对象处于设置或销毁过程中时,这些假设可能是一个问题。

    例如,在下面的代码中,观察者不知道“example”正在被销毁,可能会假定已经释放的其他属性是有效的。

    (您可能会争辩说,您的对象应该在分解之前删除所有观察者,这是一个很好的实践,也是防止意外问题的另一个准则)。

    @implementation Example
    
    -(void) setFoo:(Foo*)foo
    {
       _foo = foo;
      [_observer onPropertyChange:self object:foo];
    }
    
    -(void) dealloc
    {
       ...
       self.foo = nil;
    }
    
    @end
    
        3
  •  15
  •   mmalc    16 年前

    你回答了自己的问题:

    1. 性能本身可能是一个非常充分的原因(特别是如果访问器是原子的)。
    2. 您应该避免访问器可能产生的任何副作用。

    如果类可能是子类的话,后者尤其是一个问题。

    但不清楚为什么要在 Objul-C 2 访问器?无论您自己使用声明的属性还是写访问器,同样的原则都适用。

        4
  •  2
  •   zaph    15 年前

    可能是setter具有应该运行的逻辑,或者可能是实现使用了与getter/setter不同的名称的ivar,或者可能是需要释放的两个ivar和/或将其值设置为nil。唯一可靠的方法是调用setter。setter的职责是以这样的方式编写:在in it或dealloc期间调用时,不会出现不良的副作用。

    从“可可图案”,巴克,雅克特曼,第115页:“…当您将合成实例变量与现代的Objective-C运行时一起使用时,没有实际的替代方法来使用访问器,或者……

        5
  •  0
  •   FeifanZ    14 年前

    事实上,对于一个经常来来去去的类(像一个细节视图控制器),您希望在init中使用访问器;否则,您可能最终在viewdidUnload中释放一个您稍后尝试访问的值(它们在cs193p中显示…)

        6
  •  0
  •   Sulthan    13 年前

    您可以通过在分配/解除分配时不调用setter来创建相同的问题。

    我认为您不能通过直接在in i t/dealloc中使用retain/release来实现任何目的。您只需更改一组可能的错误。

    每次你都要考虑财产分配/解除分配的顺序。