可以从其他类访问fmdatabaseQueue

时间:2013-06-24 19:36:43

标签: ios multithreading sqlite fmdb

我有一个应用程序,使用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;"];
    }
}];

任何建议,指向进一步阅读或博客的内容都将非常感谢,感谢提前标记

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类或可能的模型类中。它使大型项目的管理变得更加容易。但无论如何你都可以做到。