Синглтон не правильно инициализируется - PullRequest
0 голосов
/ 29 апреля 2011

У меня есть следующий код, который я вызываю с помощью этого оператора: SQLiteDB * db = [[[SQLiteDB alloc] init] autorelease];

Проблема в том, что «sharedSQLiteDB» не вызывается, а скорее«allocWithZone» есть, и поэтому «checkIfDatabaseExists» не вызывается, где база данных создается.

Я не понимаю, почему ... (то есть, что я делаю не так?)

#import "SQLiteDB.h"

static SQLiteDB *sharedSQLiteDB = nil;  //  makes this a singleton class

@implementation SQLiteDB

@synthesize searchPaths, documentPath, databasePath, cDatabasePath;

#pragma mark Singleton Methods

+ (SQLiteDB *) sharedSQLiteDB  {

    if(!sharedSQLiteDB)  {
        sharedSQLiteDB = [[SQLiteDB alloc] init];
        [sharedSQLiteDB checkIfDatabaseExists];  //  check to see if d/b exists
    }
    return sharedSQLiteDB;
}   

+(id)allocWithZone:(NSZone *)zone  {  //  makes sure another instance is not allocated
    if(!sharedSQLiteDB)  {
        sharedSQLiteDB = [super allocWithZone:zone];
        return  sharedSQLiteDB;
    }
    else {
        return nil;
    }
}   

-(id)copyWithZone:(NSZone *)zone  {
    return self;
}

-(void) release  {
    //  no-op
}

Ответы [ 4 ]

1 голос
/ 29 апреля 2011

В шаблоне синглтона ваш шаблон использования должен быть:

SQLiteDB* db = [SQLiteDB sharedSQLiteDB];

То, как вы его называете, не соответствует шаблону сингелтона.Весь доступ должен осуществляться через ваше сообщение sharedSQLiteDB.

Другими словами, вы не должны инициализироваться с помощью типичных шаблонов Какао (SQLiteDB * db = [[[SQLiteDB alloc] init] autorelease]; неверен и полон проблем)) вне области действия класса.

В синглтоне, использующем шаблон инициализации по умолчанию для языка (alloc / init для ObjC или конструктор по умолчанию для C ++), должен генерировать сообщение об ошибке времени компиляции, так как constructor / initметод должен быть защищен.

См. запись Wikipedia .обратитесь к Design Pattern C ++ библии.Есть даже версия для Какао

Удачи.

0 голосов
/ 02 мая 2011

Я настоятельно рекомендую использовать заголовочный файл SyntesizeSingleton, впервые созданный Мэттом Галлахером.

Найти последнюю версию (о которой я знаю) здесь:

https://github.com/cjhanson/Objective-C-Optimized-Singleton

Это делает создание одиночных мертвецов простым.

Вот пример заголовка:

#import <Foundation/Foundation.h>
@interface Example : NSObject {}
+(Example*)sharedExample;
@end

и соответствующий .m:

#import "FMUser.h"
#import "SynthesizeSingleton.h"
@implementation Example
SYNTHESIZE_SINGLETON_FOR_CLASS(Example);
@end

[Example sharedExample] создан для вас. Это довольно мило.

0 голосов
/ 29 апреля 2011

Честно говоря, я не вижу ошибок ... Однако я публикую код, который использовал для создания Singleton. Это из источника, что теперь я не помню ссылку ... это не мой код.

static DataManager *_instance;

@implementation DataManager

+ (DataManager*)sharedInstance
{
    @synchronized(self) {

        if (_instance == nil) {

            _instance = [[super allocWithZone:NULL] init];

            // Allocate/initialize any member variables of the singleton class her
            // example
    //_instance.member = @"";
        }
    }
    return _instance;
}

#pragma mark Singleton Methods

+ (id)allocWithZone:(NSZone *)zone
{   
    return [[self sharedInstance]retain];   
}


- (id)copyWithZone:(NSZone *)zone
{
    return self;    
}

- (id)retain
{   
    return self;    
}

- (unsigned)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;    
}

Надеюсь, это поможет

0 голосов
/ 29 апреля 2011

Он не выполняет ваш + (SQLiteDB *) sharedSQLiteDB метод, потому что вы нигде не вызываете этот метод.

Как вы видели, когда вы вызываете [[SQLiteDB alloc] init], вызывается метод allocWithZone.

Измените ваш вызов на SQLiteDB *db = [SQLiteDB sharedSQLiteDB], что в этом случае вызовет ваш метод checkIfDatabaseExists.Однако если [[SQLiteDB alloc] init] вызывается где-то еще, то вызов метода checkIfDatabaseExists все равно будет пропущен.

Возможно, стоит рассмотреть вопрос о перемещении метода checkIfDatabaseExists в метод init, чтобы он вызывалсяи ваш метод синглтона и ваш allocWithZone.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...