1

私のアプリには、.sqlite ファイルに 3,000 の試験問題があります。そして、これらの質問は動的に選択され、ユーザーの要求によって並べ替えられます (たとえば、「間違った回答の数で並べ替える」、「アクセスされていない質問のみを選択する」など)。

ユーザーが選択を行うたびに、アプリは対応する SQL ステートメントを作成し、sqlite3 を使用して、すべての結果セットが NSMutableArray (Question クラス) に送信されます。ただし、お気づきのように、これには時間がかかります (約 2 ~ 3 秒かかり、その間に UI が応答しなくなります)。

したがって、rowCount() および moveToRow(int index) メソッドを持つ「カーソル」クラスを作成したいと考えています。

これで、私の考えは

Cursor c = [[Cursor alloc] init] query(
    "SELECT id,qtext,answer,a1,a2,... FROM TABLE WHERE id > 100"
)]; 
    // at this time, just a cursor is given, no need to iterate all the retrieved rows

for (i=0; i > c.rowCount(); i++) {
    c.moveToRow(i);
    ShowQuestionDetail(c);
}

このような。

CoreData がこの目的に適合することはわかっていますが、.sqlite ファイルをこのアプリの Android バージョンと共有する必要があります。CoreData では、すべてのテーブル名とフィールド名が Z_ プレフィックスで始まる必要がありますが、.sqlite ファイルのスキームを変更できません。また、sqlcipher を使用する必要があり、CoreData は sqlcipher では機能しません。

FMDB は、取得された行の数を示し、特定の行に移動するメソッドをサポートしていません。

この機能をサポートする他の SQLite ラッパー ライブラリはありますか?

誰かが、取得した行の ID のみを含む「カタログ」配列を作成し、moveToRow() が呼び出されるたびに行をフェッチすることを提案しています。それが良い代替案であることには同意しますが、別の方法を見つけたいと思っています。

4

1 に答える 1

1

別のアプローチとして、クエリを 1 行のデータに制限することもできます。つまり、cellForRowAtIndex で呼び出しを行います。私の経験から-これには別の方法を用意することをお勧めします-本当に必要な場合は、さらに一歩進んで、コアデータごとにメモリにキャッシュするための DataCache レイヤーを追加することもできます。

このようなもの.... http://code.google.com/p/airband/source/browse/trunk/airband/Classes/DataCache.h?spec=svn103&r=103

例えば。- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //セルを初期化します

 NSDictionary *dict = [self questionDataForCellAtIndexPath:indexPath];
 // set the cell values
}



-(NSDictionary*)questionDataForCellAtIndexPath:(NSIndexPath *)indexPath{

        //ENTER_METHOD;
    NSDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:0];

    NSString  *qry = [NSString stringWithFormat: @"SELECT id,qtext,answer,a1,a2,... FROM TABLE WHERE id ORDER BY id DESC limit 1 offset %d", [indexPath row]];

// you could look up here for previously accessed rows from DataCache
    //  NSDictionary *cachedRow = [DATAENV.cache objectForKey:num];
///if (cachedRow == nil) {
    //  go get it
   //   else return it 

    DLog(@"qry%@",qry );
     EGODatabaseResult *result  = [appDelegate.userdb executeQuery:qry];

    if ([result count]==0) {
        return dict;
    }
    for(EGODatabaseRow *row in result) {
        [dict setValue:[row stringForColumn:@"name"]  forKey:@"name"];

    }
    return dict;
}

EgoDatabase の私のフォークをチェックしてください。 https://github.com/jdp-global/egodatabase

非ブロッキングの非同期メソッドも含まれます。

于 2012-03-13T08:21:53.170 に答える