2

我有一个应用程序,它使用 FMDatabase 插入用户收集的数据和一些从网上下载的数据。由于对数据库的同时请求太多,我目前正在崩溃。

我想通过我的应用程序并将 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;"];
    }
}];

任何建议,进一步阅读或博客的指针将不胜感激,在此先感谢

4

1 回答 1

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单例(顺便说一句,按照惯例,您的类名应该以大写字母开头),并为该FMDatabaseQueue对象创建一个单例。然后,在inDatabase块内部,您可以只引用db参数,而不引用任何外部数据库对象。

请注意,我已将我的单例设为NSObject子类,并且FMDatabaseQueue是该类的公共属性。你在这里有很多选择。例如,您也可以使单例FMDatabaseQueue本身成为子类(就像您对当前databaseModel对象所做的那样,它似乎是FMDatabase子类)。或者,根据我的个人喜好,我实际上将FMDatabaseQueue对象设为我的私有财产DatabaseManager并从我的控制器等中删除任何 FMDB 代码。我将所有 FMDB 代码保存在这个新的单例中,或者可能保存在我的模型对象中。当您有大型项目时,您可能不希望 SQL 语句到处乱扔。个人认为 FMDB 代码和 SQL 语句是一个实现细节,应该封装在DatabaseManager类中,或者可能是模型类中。它使大型项目的管理变得更加容易。但是你可以随心所欲地做。

于 2013-06-24T22:22:14.677 回答