2

FMDatabase を使用して、ユーザーが収集したデータと Web からダウンロードしたデータを挿入するアプリがあります。現在、データベースへの同時リクエストが多すぎるため、いくつかのクラッシュが発生しています。

アプリを調べて、すべてのデータベース操作に FMDatabaseQueue を追加したいのですが、Web からデータをダウンロードしてデータベースに挿入するバックグラウンド クラスがあり、アクセスする必要があるため、アプリ全体に 1 つのキューが必要です。ユーザーに表示される UITableView を設定するためのデータベース。

私の質問は、すべてのクラスで参照される静的な FMDatabaseQueue を作成できますか?

2 番目の質問は、クエリが現在次の形式であるかどうかです。

 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 に答える