Nucc
Nucc

Reputation:

Objective-c static instance

I'd like to create database based models, so I wanna use my own DatabaseModel class to manage the database connection, and every class that uses database is derived from it (it would be a mapping between the model and the table). I'm using a sqlite API.

Since I need only one database connection instance, I created a static variable to store the connection instance

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

In this case [database retain] throws a bad_access exception. I don't understand exactly, when database is a static variable, why I get this message...

Upvotes: 2

Views: 11802

Answers (4)

Daniel Dickison
Daniel Dickison

Reputation: 21882

In your +open method, you have:

database = [DBAPI open];

If DBAPI is following standard Cocoa memory rules, the returned instance is not retained (usually it's autoreleased). So by the time you access it in +getDatabase the instance may already have been released.

Simple fix would be to retain the instance:

database = [[DBAPI open] retain];

A better approach would be to adopt the singleton pattern as others have mentioned.

Upvotes: 1

Nucc
Nucc

Reputation:

Sorry guys!

It was my mistake. In Open() function the API asks for an (NSString*) sqlite path. And I forgot to retain that variable. (I'm sometimes in trouble with objective-c memory management, sorry)

Now I'm creating the variable without static keyword on the base class, and using extern keyword to reach in the subclasses, and does it work.

With static keyword it's invisible from derived classes...

Upvotes: 0

Nathan Kinsinger
Nathan Kinsinger

Reputation: 25011

  1. It doesn't look like you create the object anywhere. You need to alloc and init the object before you can use it.
  2. You should not be retaining the static object every time someone calls +getDatabase. This will cause the object to be over retained and there is really no reason for it, once you alloc and init it then the static variable will own it and you don't need any more retains.

Cocoa has a design pattern call Singleton that would work well here. You create a single instance of a class and then have a method (often along the lines of +sharedClassName) that returns that instance.

For more reading there is some good information at CocoaDev regarding the singleton design pattern and Cocoa with Love has a good article on Singletons, AppDelegates and top-level data.

Upvotes: 3

David Salzer
David Salzer

Reputation: 872

This error actually saying that the database variable is still null. I dont see any init call of the database variable or allocation. Am I missing anything?

Upvotes: 0

Related Questions