使用 AppDelegate 的变量作为全局变量 - 关于释放/保留的问题

Posted

技术标签:

【中文标题】使用 AppDelegate 的变量作为全局变量 - 关于释放/保留的问题【英文标题】:Using Variable of AppDelegate as a Global Variable - question regarding release/retain 【发布时间】:2010-07-08 22:06:32 【问题描述】:

我在 AppDelegate 中创建了一个名为“myDBManager”的变量:

@interface myAppDelegate : NSObject <UIApplicationDelegate> 
   MyDBManager *myDBManager;

@property (nonatomic, retain)  MyDBManager *myDBManager;

@end

我在大多数其他类中将其用作保存所有关键应用程序数据的全局变量。它只会被创建一次,并且只会在最后死去。因此,例如在 AnyOtherClass 中访问 myDBManager

@interface AnyOtherClass :  UITableViewController 
   MyDBManager *myDBManager;
   NSObject *otherVar;

@property (nonatomic,retain)   MyDBManager *myDBManager;
@property (nonatomic,retain)   NSObject *otherVar;
@end

//getting the data from "global" myDBManager and putting it into local var of AnyOtherClass
- (void)viewWillAppear:(BOOL)animated 
   //get the myDBManager global Object
   MyAppDelegate *mainDelegate = (MyAppDelegate *)[[UIApplication sharedApplication]delegate];
   myDBManager = mainDelegate.myDBManager;
   


-  (void)dealloc 
       [otherVar release];
        //[dancesDBManager release]; DO NOT RELEASE THIS SINCE ITS USED AS A GLOBAL VARIABLE!
        [super dealloc];
        

这是我的问题:虽然 AnyOtherClass 的所有其他局部变量,例如“otherVar”,都必须在 AnyOtherClass 的 dealloc 方法中释放(总是 - 对吗?),但在 AnyOtherClass 中释放 myDBManager 会导致应用程序出错.

所以我永远不会在我的应用程序的任何类中释放本地 myDBManager 变量 - 所有其他局部变量总是被释放 - 它工作正常。 (甚至检查 retainCount)。

我是对的,类的所有局部变量都需要在该类的 dealloc 中释放,或者实际上可以,在使用所描述的全局变量构造的情况下根本不释放这些变量? (或任何其他情况?)

非常感谢您的帮助!

【问题讨论】:

【参考方案1】:

在您的场景中,myDBManager 不是全局变量或局部变量,它是自动保留的属性(标有 retain)。根据The Objective-C Programming Language: Declared Properties,nonatomic,retain 属性应该在dealloc 中显式释放。但是,如果您的属性是合成的,则您无权访问支持成员变量,因此您不能在其上调用 release;您必须使用属性设置器将其设置为nil,这会将release 发送到之前的值。您是否有机会将AnyOtherClassmyAppDelegate 中的myDBManager 属性设置为nil

更新:@Don 的回答实际上是正确的。您没有调用属性设置器 (self.myDBManager),因此不会启动自动保留。我会留下我的答案,以便人们从我的错误中吸取教训。 :-)

【讨论】:

【参考方案2】:

当你在 AnyOtherClass 中引用它时,你并没有保留它,所以在那个时候释放它不是你的。您正在直接设置 ivar,因此该属性的保留不起作用。如果你打电话给

self.myDBManager = mainDelegate.myDBManager;

你会保留它,并且在你释放类时必须释放它。

但是,如果它是一个全局变量,为什么不在 AnyOtherClass 中那样使用它呢?当您需要数据库管理器时,为什么不打电话给mainDelegate.myDBManager

【讨论】:

...因为使用“mainDelegate.myDBManager”需要“MyAppDelegate *mainDelegate = (MyAppDelegate *)[[UIApplication sharedApplication]delegate];”而且文本太多,难以阅读。变量“myDBManager”是“AnyOtherClass”的局部变量,所以我可以很容易地在这个类的所有方法中使用它。但感谢您的澄清!因此,如果 ivar 只是在没有“self.xx”的情况下被分配,我永远不会释放! (当然,如果它被分配了,我需要释放 - 但那是不同的情况)对吗? 不,如果您将属性声明为retain,您应该始终保留它,然后在dealloc中释放它。这样,无论是直接在类中设置还是调用属性,您都可以获得一致的行为。确实,您应该始终使用self.property 以确保它按您预期的方式运行。但请参阅 Franci 的回答,了解何时应该做什么的详细解释。 要清楚一点:如果你不使用该属性,你应该把这个:myDBManager = mainDelegate.myDBManager;改成这个:myDBManager = [mainDelegate.myDBManager retain];但我还是推荐self.myDBManager = mainDelegate.myDBManager;

以上是关于使用 AppDelegate 的变量作为全局变量 - 关于释放/保留的问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS全局变量的声明和使用

应用程序委托中的全局变量未保存

ViewController() 比 appDelegate() 先调用?

详解Objective-C中静态变量使用方法

iPhone,如何使用 App Delegate 变量使其可以像全局变量一样使用?

Golang 模板 - 使用模板变量作为范围循环内的全局变量