有一些我似乎没有得到iOS的属性和内存管理!
在我的AppDelegate
,我想要一个NSString *
财产:
.h
文件中以这种方式声明:
@property(非原子,复制)NSString * myString;.m
合成它。我的一个方法使用这样的属性:
myString = [notificationDictionary objectForKey:@"myKey"];
(notificationDictionary
是NSDictionary*
,我在application:didFinishLaunchingWithOptions:
的launchOptions
字典中获得了关键的UIApplicationLaunchOptionsRemoteNotificationKey
)
我认为这意味着我的AppDelegate
拥有自己的myString
副本,保留计数为1,对吧?
然后另一种方法尝试访问该属性,但我得到一个EXC_BAD_ACCESS
异常。
为了100%确定发生了什么,我多次保留我的属性并在每次访问时显示其保留计数的值:保留计数在我给我的属性赋值的方法和我读它的方法。
哪个对象将release方法发送到我的字符串?
这一行:
myString = [notificationDictionary objectForKey:@"myKey"];
不使用您的综合属性访问器。它只是直接设置实例变量,并绕过自动复制行为。
为了使用您的属性访问器,您需要添加self.
,如下所示:
self.myString = [notificationDictionary objectForKey:@"myKey"];
更新:我在这里更详细地回答了类似的问题:why-does-this-property-need-the-retain?
更新#2:为了进一步解释,向你的myString
变量发送释放消息的“神秘对象”实际上是NSAutoreleasePool的一个实例,很可能是与你的主线程相关联的池。 [notificationDictionary objectForKey:...]
返回的值是自动释放的,因此当您将此值分配给myString
时,它将持续到当前运行循环结束。当运行循环结束时,它会耗尽自动释放池,将release
发送到任何已标记为自动释放的对象。在发生这种情况之后,myString
中的指针值引用了已释放的内存块。这种类型的死指针通常称为僵尸。当您尝试向僵尸发送消息时,通常会发生EXC_BAD_ACCESS异常。