Objective-c static instance
我想创建基于数据库的模型,所以我想使用我自己的databaseModel类来管理数据库连接,并且使用数据库的每个类都是从它派生出来的(它将是模型和表之间的映射)。我正在使用sqlite API。
因为我只需要一个数据库连接实例,所以我创建了一个静态变量来存储连接实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | DatabaseModel.h --------------- @interface DatabaseModel : NSObject { } // the connection instance static FMDatabase *database; +(BOOL) open; +(void) close; +(id)getDatabase; @end DatabaseModel.m --------------- // Is it necassary? static FMDatabase *database = nil; @implementation DatabaseModel +(BOOL) open { // make connection (doodled code) database = [DBAPI open]; } +(void) close { // ... } +(id)getDatabase { // Throws bad_memory_access [database retain]; return database; } @end MyClass.h --------- @interface MyClass : DatabaseModel { } -(void) foobar; @end MyClass.m --------- @implementation MyClass -(void) foobar { // This assign doesn't work database = [DatabaseModel getDatabase]; } @end |
在这种情况下,[数据库保留]会引发一个错误的访问异常。我不太明白,当数据库是静态变量时,为什么会收到这个消息…
Cocoa有一个名为singleton的设计模式,在这里可以很好地工作。创建类的单个实例,然后使用返回该实例的方法(通常沿+sharedclassname行)。
对于更多的阅读,CocaDev有一些关于单体设计模式的好信息,Cocoa with Love有一篇关于单体、AppDelegate和顶级数据的好文章。
在您的
1 | database = [DBAPI open]; |
如果dbapi遵循标准的cocoa内存规则,则不会保留返回的实例(通常是自动释放的)。所以当您在
简单的解决方法是保留实例:
1 | database = [[DBAPI open] retain]; |
一个更好的方法是像其他人提到的那样采用单例模式。
对不起伙计们!
这是我的错。在open()函数中,API请求(nsstring*)sqlite路径。我忘了保留这个变量。(我有时会遇到Objective-C内存管理的问题,对不起)
现在,我在基类上创建了一个不带静态关键字的变量,并使用extern关键字来访问子类,它是否工作。
对于静态关键字,它在派生类中不可见…
此错误实际上表示数据库变量仍然为空。我没有看到任何数据库变量或分配的初始化调用。我错过什么了吗?