我有一个应用程序,使用FMDatabase插入用户收集的数据和从Web下载的一些数据。由于对数据库的同时请求太多,我目前正在崩溃。
我想通过我的应用程序并将FMDatabaseQueue添加到我的所有数据库操作中,但是我需要一个队列用于整个应用程序,因为我有从Web下载数据并将其插入数据库的后台类,我有访问数据库以填充用户看到的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;"];
}
}];
任何建议,指向进一步阅读或博客的内容都将非常感谢,感谢提前标记
答案 0 :(得分:7)
有两种方法可以通过不同的课程访问FMDatabaseQueue
。单例,使其成为应用程序委托的属性(可以通过从[[UIApplication sharedApplication] delegate]
检索应用程序的委托来检索),或者在第一个视图控制器中创建并传递它。
就个人而言,我倾向于单身对象,比如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
单例(BTW,按照惯例,您的类名应以大写字母开头),并为FMDatabaseQueue
对象创建单例。然后,在inDatabase
块内,您可以引用db
参数,而不是引用任何外部数据库对象。
注意,我已将我的单例设为NSObject
子类,FMDatabaseQueue
是该类的公共属性。你有很多选择。例如,您可以将单例设置为FMDatabaseQueue
子类本身(有点像您显然使用当前的databaseModel
对象,它似乎是FMDatabase
子类。或者,根据我个人的偏好,我实际上将FMDatabaseQueue
对象设为DatabaseManager
的私有属性,并从我的控制器等处删除任何FMDB代码。我保留所有FMDB代码在这个新的单例中,或者可能在我的模型对象中。当您获得大型项目时,您可能不希望SQL语句遍布整个地方。就个人而言,我认为FMDB代码和SQL语句是一个实现细节,应该封装在DatabaseManager
类或可能的模型类中。它使大型项目的管理变得更加容易。但无论如何你都可以做到。