_fmdatabaseQueue 可以从其他类访问吗

Posted

技术标签:

【中文标题】_fmdatabaseQueue 可以从其他类访问吗【英文标题】:can fmdatabaseQueues be accesed from other classes 【发布时间】:2013-06-24 19:36:42 【问题描述】:

我有一个应用程序,它使用 FMDatabase 插入用户收集的数据和一些从网络下载的数据。由于对数据库的并发请求过多,我目前遇到了一些崩溃。

我想通过我的应用程序并将 FMDatabaseQueue 添加到我的所有数据库操作中,但是我需要为整个应用程序创建一个队列,因为我有从网络下载数据并将其插入数据库的后台类,我有访问数据库以填充用户看到的 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】:

有几种方法可以让您的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 类中,或者可能是模型类中。它使大型项目的管理变得更加容易。但你可以随心所欲。

【讨论】:

Rob,感谢您的回答,这样我就清楚我不需要打开或关闭数据库了? @MarkGilchrist 您不必打开它。您使用[FMDatabaseQueue databaseQueueWithPath:path][[FMDatabaseQueue alloc] initWithPath:path] 创建队列,然后发出inDatabase 方法。 FMDatabaseQueue 将为您打开数据库。 好的,我已经更改了我所有的代码,它运行良好,感谢一百万的这个

以上是关于_fmdatabaseQueue 可以从其他类访问吗的主要内容,如果未能解决你的问题,请参考以下文章

执行 [FMDatabaseQueue inDatabase:] 后出现错误,因为周围至少有一个打开的结果集?

使用 Swift 的 FMDatabaseQueue (FMDB)

FMDatabaseQueue 如何返回一个值

使用多线程读取 FMDB 数据库

FMDatabaseQueue 被称为可重入错误

从其他类Objective-C访问方法