【问题标题】:Which object did send a "release" message to my property?哪个对象向我的财产发送了“释放”消息?
【发布时间】:2010-07-29 10:20:02
【问题描述】:

关于 iOS 的属性和内存管理,我似乎不了解一些东西!

在我的AppDelegate 中,我想要一个NSString * 属性:

  • 我已经在.h 文件中这样声明它:

    @property(非原子,复制)NSString *myString;

  • 并在.m中合成。

我的一个方法使用这样的属性:

myString = [notificationDictionary objectForKey:@"myKey"];

notificationDictionaryNSDictionary* 我在application:didFinishLaunchingWithOptions:launchOptions 字典中使用键UIApplicationLaunchOptionsRemoteNotificationKey

我认为这意味着我的 AppDelegate 拥有自己的 myString 副本,保留计数为 1,对吧?

然后另一个方法尝试访问该属性,但我得到一个EXC_BAD_ACCESS 异常。

为了 100% 确定发生了什么,我已多次保留我的财产,并在每次访问时显示其保留计数的值:保留计数在我为我的赋值的方法之间的某个位置递减属性和我阅读它的方法。

哪个对象将释放方法发送到我的字符串?

【问题讨论】:

    标签: objective-c memory-management properties variable-assignment


    【解决方案1】:

    这一行:

    myString = [notificationDictionary objectForKey:@"myKey"];
    

    是否使用您的合成属性访问器。它只是直接设置实例变量,并绕过自动复制行为。

    为了使用您的属性访问器,您需要添加self.,如下所示:

    self.myString = [notificationDictionary objectForKey:@"myKey"];
    

    更新:我在这里更详细地回答了一个类似的问题:why-does-this-property-need-the-retain?

    更新 #2: 进一步解释一下,向您的 myString 变量发送发布消息的“神秘对象”实际上是 @ 的一个实例987654322@,很可能是与您的主线程关联的池。 [notificationDictionary objectForKey:...] 返回的值是自动释放的,所以当你将此值分配给myString 时,它只会持续到当前运行循环结束。当运行循环完成时,它会清空自动释放池,将release 发送到任何已标记为自动释放的对象。之后,myString 中的指针值引用了一块已释放的内存。这种类型的死指针通常被称为僵尸。当您尝试向僵尸发送消息时,通常会发生 EXC_BAD_ACCESS 异常。

    【讨论】:

    • 哇!再次感谢 !那是我真正需要知道的! :) (虽然我认为 Apple 文档对于他们的 API 来说确实做得很好,但我认为他们关于基本 Objective-C 概念的文档很难找到并且相当暗示)。无论如何,再次感谢!
    • 别担心! :)如果您正在寻找一些有关基本概念的阅读材料,苹果的内存管理指南是一个不错的起点:developer.apple.com/mac/library/documentation/cocoa/conceptual/…
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多