我有一个使用FMDatabase插入用户收集的数据和一些从Web下载的数据的应用程序。由于对数据库的同步请求过多,我目前遇到了一些崩溃。
我想浏览我的应用程序并将FMDatabaseQueue添加到我的所有数据库操作中,但是我需要为整个应用程序使用一个队列,因为我有一些后台类,这些类可以从Web上下载数据并将其插入到db中,所以我必须访问数据库以填充用户看到的UITableView。
所以我的问题是,您能否创建所有类中都引用的静态FMDatabaseQueue?
我的第二个问题是我的查询当前是否采用以下格式:
FMResultset *result= [[databaseModel sharedInstance]executeQuery:@"SELECT * FROM TABLE1"];
if(![result next]){
[[databaseModel sharedInstance]executeUpdate:@"UPDATE TABLE1 SET foo=bar where 1;"];
这会变成吗?
[dbQueue inDatabase(FMdatabase db) ^{ //dbQueue is declared statically
FMResultset *result= [[databaseModel sharedInstance]executeQuery:@"SELECT * FROM TABLE1"];
if(![result next]){
[[databaseModel sharedInstance]executeUpdate:@"UPDATE TABLE1 SET foo=bar where 1;"];
}
}];
在此先感谢您的任何建议,指向进一步阅读的建议或博客。
最佳答案
有两种方法可以使您的FMDatabaseQueue
通过不同的类进行访问。将其设为您的应用程序委托(delegate)的属性(可以通过从[[UIApplication sharedApplication] delegate]
检索应用程序的委托(delegate)进行检索),或者在您的第一个 View Controller 中创建并传递它。
就我个人而言,我倾向于singleton对象,比如DatabaseManager
。 @interface
文件可能如下所示:
//
// DatabaseManager.h
// Database Manager Example
//
// Created by Robert Ryan on 6/24/13.
// Copyright (c) 2013 Robert Ryan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "FMDatabaseQueue.h"
@interface DatabaseManager : NSObject
@property (nonatomic, strong) FMDatabaseQueue *databaseQueue;
+ (instancetype)sharedManager;
@end
@implementation
可能类似于://
// DatabaseManager.m
// Database Manager Example
//
// Created by Robert Ryan on 6/24/13.
// Copyright (c) 2013 Robert Ryan. All rights reserved.
//
#import "DatabaseManager.h"
@implementation DatabaseManager
+ (instancetype)sharedManager
{
static id sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init
{
self = [super init];
if (self) {
_databaseQueue = [[FMDatabaseQueue alloc] initWithPath:[self databasePath]];
}
return self;
}
- (NSString *)databasePath
{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
return [docsPath stringByAppendingPathComponent:@"test.sqlite"];
}
@end
然后,当您要使用此单例时,包括
DatabaseManager.h
头文件,您可以执行以下操作:#import "ViewController.h"
#import "DatabaseManager.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
DatabaseManager *databaseManager = [DatabaseManager sharedManager];
[databaseManager.databaseQueue inDatabase:^(FMDatabase *db) {
FMResultSet *result = [db executeQuery:@"SELECT * FROM TABLE1"];
if (!result) {
NSLog(@"%s: executeQuery error: %@", __FUNCTION__, [db lastErrorMessage]);
return;
}
while ([result next]) {
// do whatever you want with the results
}
[result close];
}];
}
// the rest of your code here
@end
简而言之,您想退休
databaseModel
单例(顺便说一句,按照惯例,您的类名应以大写字母开头),并为FMDatabaseQueue
对象创建一个单例。然后,在inDatabase
块内部,您仅可以引用db
参数,而不引用任何外部数据库对象。注意,我已经将我的单例设为
NSObject
子类,并且FMDatabaseQueue
是该类的公共(public)属性。您在这里有很多选择。例如,您还可以使单例成为FMDatabaseQueue
子类本身(类似于您显然对当前的databaseModel
对象,它似乎是FMDatabase
子类)。另外,根据我的个人喜好,我实际上使FMDatabaseQueue
对象成为DatabaseManager
的私有(private)属性,并从 Controller 中删除所有FMDB代码,等等。我将所有FMDB代码保留在这个新的单例中,或者可能在我的模型对象中。当您获得大型项目时,您可能不希望到处都是SQL语句。我个人认为FMDB代码和SQL语句是一个实现细节,应该封装在DatabaseManager
类或模型类中。这样,大型项目的管理就容易一些。但是您可以按照自己的意愿进行操作。