Objective-c статический экземпляр - PullRequest
2 голосов
/ 07 июня 2009

Я хотел бы создать модели на основе базы данных, поэтому я хочу использовать свой собственный класс DatabaseModel для управления соединением с базой данных, и каждый класс, использующий базу данных, получен из нее (это будет отображение между моделью и таблицей) , Я использую API sqlite.

Поскольку мне нужен только один экземпляр подключения к базе данных, я создал статическую переменную для хранения экземпляра подключения

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

В этом случае [сохранение базы данных] вызывает исключение bad_access. Я не совсем понимаю, когда база данных является статической переменной, почему я получаю это сообщение ...

Ответы [ 4 ]

3 голосов
/ 07 июня 2009
  1. Не похоже, что вы создаете возражать где угодно Вы должны выделить и инициировать объект, прежде чем вы сможете используйте это.
  2. Вы не должны сохранять статический объект каждый раз, когда кто-то вызывает + getDatabase. Это приведет к чрезмерному сохранению объекта, и на самом деле для этого нет никаких причин, как только вы выделите и инициализируете его, статическая переменная станет его владельцем, и вам больше не нужно будет сохранять.

Какао имеет шаблонный вызов Singleton , который бы хорошо работал здесь. Вы создаете один экземпляр класса, а затем имеете метод (часто по типу + sharedClassName), который возвращает этот экземпляр.

Для получения дополнительной информации в CocoaDev есть некоторая полезная информация о одноместном шаблоне проектирования , а в Cocoa with Love есть хорошая статья о Одиночных, AppDelegates и данных верхнего уровня .

1 голос
/ 07 июня 2009

В вашем +open методе у вас есть:

database = [DBAPI open];

Если DBAPI следует стандартным правилам памяти Какао, возвращенный экземпляр не сохраняется (обычно он автоматически высвобождается). Таким образом, к моменту обращения к нему в +getDatabase экземпляр уже может быть освобожден.

Простым решением было бы сохранить экземпляр:

database = [[DBAPI open] retain];

Лучшим подходом было бы принять шаблон синглтона, как уже упоминали другие.

0 голосов
/ 07 июня 2009

Простите, ребята!

Это была моя ошибка. В функции Open () API запрашивает путь (NSString *) sqlite. И я забыл сохранить эту переменную. (У меня иногда проблемы с управлением памятью Objective-C, извините)

Теперь я создаю переменную без статического ключевого слова в базовом классе и использую ключевое слово extern для доступа к подклассам, и это работает.

Со статическим ключевым словом он невидим для производных классов ...

0 голосов
/ 07 июня 2009

Эта ошибка фактически говорит о том, что переменная базы данных по-прежнему равна нулю. Я не вижу никакого вызова инициализации переменной базы данных или распределения. Я что-то упустил?

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