Sebastian
Sebastian

Reputation: 972

Singleton in static library in iOS

I have a static library which contains a Singleton class (FMDB SQLite Data Access), now I open from my main application the connection and do thingss... this works, after that a method in my library want to call the a method on my singleton and I get the error that

-[FMDatabase executeQuery:withArgumentsInArray:]: message sent to deallocated instance 0xa443960

is this not possible what I'm trying to achieve?

this is short version of my singleton

    static MySingleton* _sharedMySingleton = nil;

    FMDatabase *database;

     #ifndef __clang_analyzer__
    +(MySingleton*)sharedMySingleton
     {
    @synchronized([MySingleton class])
    {
        if (!_sharedMySingleton)
            [[self alloc] init];

        return _sharedMySingleton;
    }
      }
      #endif

    +(id)alloc
     {
    @synchronized([MySingleton class])
    {
        NSAssert(_sharedMySingleton == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedMySingleton = [super alloc];
        return _sharedMySingleton;
    }
     }

     -(Resource *)getResourceForName:(NSString *)name
    {    
    NSString *select = @"SELECT Data, MimeType FROM File WHERE FileName = ? LIMIT 1";

    NSArray *arguments = [NSArray arrayWithObject:[NSString stringWithFormat:@"/%@", name]];

    FMResultSet *s = [database executeQuery:select withArgumentsInArray:arguments];

    if (s == NULL)
    {
        FuncFileLog(@"getResourceForName file cant be loaded: %@", [database lastErrorMessage]);
        return nil;
    }
    NSData *data = nil;
    NSString *mimeType;

    while ([s next])
    {
        data = [NSData dataFromBase64String:[s stringForColumnIndex:0]];
        mimeType = [s stringForColumnIndex:1];
    }

    Resource *resource = [[[Resource alloc] initWithData:data mimeType:mimeType] autorelease];

    return resource;
    }

    -(BOOL)openDatabase
    {
    database = [FMDatabase databaseWithPath:[self getDocumentResourcePath]];
    return [database open];
    }

     -(void)closeDatabase
   {
        [database close];
       [database release];
   }

    -(void)dealloc
    {
    if (database != NULL)
    {
        [self closeDatabase];
    }
    [baseUrl release];
    [super dealloc];
    }

    @end

EDIT:

I found that the dealloc from FMDatabase gets called after my application start return, but dont know why.

EDIT2:

Currently I thought one problem was this line

database = [FMDatabase databaseWithPath:[self getDocumentResourcePath]]; here I have to retain the object.

Upvotes: 2

Views: 734

Answers (1)

trojanfoe
trojanfoe

Reputation: 122391

You don't actually assign the singleton instance:

if (!_sharedMySingleton)
    [[self alloc] init];

should be:

if (!_sharedMySingleton)
     _sharedMySingleton = [[self alloc] init];

and dump that overridden alloc method.

Also database should be an instance variable in the class, and not at global scope.

Upvotes: 1

Related Questions