【问题标题】:strong, weak, and id强、弱和本我
【发布时间】:2012-07-21 04:24:31
【问题描述】:

在 iOS 3.0 发布时,我曾做过一些 iOS 的开发,但两年来我都忘记了 iOS 的表现。

我记得你确实会在 iOS 3.0 中保留,即使如此,我仍然不记得保留在 setter 中的确切原因是什么。到目前为止,这只是困扰我的一件事。

最后但并非最不重要的一点是,在带有 ARC 的 iOS 5 中,默认情况下局部变量很强大。如果他们中的一些人没有二传手,他们怎么能强大呢? (例如,id。)

一些代码来解释我的意思:

+(double) popOperandOffStack:(NSMutableArray *) stack{
    double result = 0;

    id topOfStack = [stack lastObject];

// how is topOfStack retaining [stack lastObject] if it's simply id?

    if (topOfStack) [stack removeLastObject];

    if ([topOfStack isKindOfClass:[NSNumber class]]){
        result = [topOfStack doubleValue];
    }
    else if ([topOfStack isKindOfClass:[NSString class]]){

        if ([topOfStack isEqualToString:@"+"]){
            result = [self popOperandOffStack:stack] + [self popOperandOffStack:stack];
        }

        if ([topOfStack isEqualToString:@"-"]){
            result = [self popOperandOffStack:stack] - [self popOperandOffStack:stack];
        }

        if ([topOfStack isEqualToString:@"*"]){
            result = [self popOperandOffStack:stack] * [self popOperandOffStack:stack];
        }

        if ([topOfStack isEqualToString:@"/"]){
            result = [self popOperandOffStack:stack] / [self popOperandOffStack:stack];
        }


    }

    return result;
}

【问题讨论】:

  • 使用 ARC,您可以在不考虑保留/自动释放/释放的情况下进行编程。只需关心这一点,即可为属性声明创建的 ivar 和隐式 ivar 提供正确的强/弱属性。
  • 你能解释清楚一点吗?我不明白你的意思。第二句。
  • “如果其中一些没有设置器”是什么意思?
  • topOfStack 正在持有另一个对象,并且在将其从 NSMutableArray 中删除之后仍然持有该对象。如果它只是类型 id,它是如何做到的? id 变量在后台有 setter 方法吗?

标签: iphone objective-c memory-management


【解决方案1】:

您可以在编译时不知道它们的确切类型的情况下向对象发送消息。事实上,当您向从数组返回的对象发送消息时,您通常会这样做:您不需要将id 转换为确切的类型,您只需发送一条消息,Objective C 就会正确地调度它。此规则的唯一例外是使用点 . 语法访问属性:您确实需要在那里进行强制转换。

类继承自NSObject 的每个对象都会响应retainreleaseautorelease 等。这就是 ARC 需要知道的全部内容。在最坏的情况下,如果您遇到的 id 恰好指向无效的内容,您将收到“对象不响应选择器”消息。

【讨论】:

  • “Objective C 会正确调度它”——当然,假设编译器选择了正确的方法签名!
  • @tc。等等,我以为编译器对签名的猜测是为了发出错误或警告,编译器可能对此有误。但是就运行时分派而言,当签名在编译时固定时,编译器就退出了循环:一个对象要么响应选择器,要么不响应。如果没有,则抛出异常。
  • 如果有两个方法(在不同的类中)具有相同的选择器但方法签名不兼容,但编译器只知道其中一个(因为您没有#include 另一个的标头),它不会发出警告。
【解决方案2】:

您似乎将属性与实例变量和局部变量混淆了。

变量没有设置器。属性有设置器。 任何类型的属性都可以有setter(除了可能的void)。实例变量可能恰好对应于属性,但变量本身没有“setter”。 obj->ivar 永远不会调用 setter,即使在 ARC 下也不会

ARC 只做了大约三件事:

  1. 为您插入 retainreleaseautoreleasedealloc。当你写

    // ARC
    {
      id foo = [array lastObject];
      ...
    }
    

    它被翻译成大约

    // MRC
    {
      id foo = [[array lastObject] retain];
      ...
      [foo release];
    }
    

    它使用 Objective-C 命名约定来确定需要保留和释放的内容。有一些优化(它实际上使用objc_retain() 和朋友在ARC spec 中描述的原因,加上一些函数比-autorelease 更有效地处理自动释放的对象。)

  2. -dealloc 中为您发布__strong ivars。它不调用属性设置器;它只是释放 ivars。它也可能将它们设置为nil

  3. 清零弱引用。__weak 变量由objc_copyWeak() 和朋友读取/写入,而不是直接访问。在-[NSObject release](或左右)中还有一个钩子,以便正确实现归零弱引用。

此外,围绕块和__block 变量的语义以一种不易通过 MRC 复制的方式进行更改。除此之外,我相信 ARC 所做的一切都可以通过调用 ARC 运行时支持函数调用来复制。

ARC 和 setter 之间的唯一联系是您可以摆脱很多属性,因为编译器在 ivar 访问时插入了保留/释放。

【讨论】:

  • 但在 iOS 5 中,'strong' 属性关键字不是用作保留的同义词吗?如果你能请清除这一点。我猜他们是两个不同的东西。
  • properties 中,是的,但仅在属性中,这与 ARC 无关 — 您可以使用 @property (strong) 而不使用 ARC。我认为他们更改了名称,因此与 weak 形成对比。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 2016-11-03
  • 2012-06-25
相关资源
最近更新 更多