Objective-c静态实例

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

在这种情况下,[数据库保留]会引发一个错误的访问异常。我不太明白,当数据库是静态变量时,为什么会收到这个消息…


  • 看起来不像是你创造的任何地方都有。你需要分配先初始化对象用它。
  • 不应该每次有人调用+getdatabase时都保留静态对象。这将导致对象被过度保留,并且实际上没有理由这样做,一旦您分配并初始化了它,那么静态变量将拥有它,您不需要再保留了。
  • Cocoa有一个名为singleton的设计模式,在这里可以很好地工作。创建类的单个实例,然后使用返回该实例的方法(通常沿+sharedclassname行)。

    对于更多的阅读,CocaDev有一些关于单体设计模式的好信息,Cocoa with Love有一篇关于单体、AppDelegate和顶级数据的好文章。


    在您的+open方法中,您有:

    1
    database = [DBAPI open];

    如果dbapi遵循标准的cocoa内存规则,则不会保留返回的实例(通常是自动释放的)。所以当您在+getDatabase中访问它时,该实例可能已经被释放了。

    简单的解决方法是保留实例:

    1
    database = [[DBAPI open] retain];

    一个更好的方法是像其他人提到的那样采用单例模式。


    对不起伙计们!

    这是我的错。在open()函数中,API请求(nsstring*)sqlite路径。我忘了保留这个变量。(我有时会遇到Objective-C内存管理的问题,对不起)

    现在,我在基类上创建了一个不带静态关键字的变量,并使用extern关键字来访问子类,它是否工作。

    对于静态关键字,它在派生类中不可见…


    此错误实际上表示数据库变量仍然为空。我没有看到任何数据库变量或分配的初始化调用。我错过什么了吗?