1

ネットワーク経由でxmlフィードを取得し、それを解析してsqlite dbに保存し、ユーザーに表示するiosアプリを作成しています。

私の xml フィードの長さは約 1700 行です: http://www.paulshin.ca/yunatube/res/en.xml

これが私のアプリの動作方法です。

  1. ユーザーがアプリを実行します
  2. アプリはネットワーク経由で xml を取得します
  3. xmlパーサーを使用してxmlオブジェクトをループし、各アイテムをsqlite dbに保存します
  4. 完了したら、テーブルビューにアイテムを表示します..

ただし、ステップ 2 には 5 秒もかからず、ステップ 3 には約 20 秒かかることがわかりました。その理由は、各項目をデータベースに格納するのに時間がかかるためです。

以下は、ステップ3で使用するものです。

TBXMLElement *elemRoot = nil, *youtube = nil, *maincateg = nil, *categ = nil, *clip = nil;

    // maincatg
    NSString *mcTitle = nil;
    // catge
    NSString *cTitle = nil;
    // clip
    NSString *title = nil, *url = nil, *note = nil;

    elemRoot = tbxml.rootXMLElement;

    if (elemRoot) {
        youtube = [TBXML childElementNamed:@"youtube" parentElement:elemRoot];
        maincateg = [TBXML childElementNamed:@"maincateg" parentElement:youtube];

        while (maincateg) {
            mcTitle = [TBXML valueOfAttributeNamed:@"type" forElement:maincateg];

            categ = [TBXML childElementNamed:@"category" parentElement:maincateg];
            while (categ) {
                cTitle = [TBXML valueOfAttributeNamed:@"title" forElement:categ];

                clip = [TBXML childElementNamed:@"clip" parentElement:categ];
                while (clip) {
                    title = [TBXML valueOfAttributeNamed:@"title" forElement:clip];
                    url = [TBXML valueOfAttributeNamed:@"url" forElement:clip];
                    note = [TBXML valueOfAttributeNamed:@"note" forElement:clip];

                    //TODO
                    if (![note isEqualToString:@"0"]) {
                        // save pared data to persistent

                        title = [title stringByReplacingOccurrencesOfString:@"&"
                                                                 withString:@"&"];
                        cTitle = [cTitle stringByReplacingOccurrencesOfString:@"&"
                                                                 withString:@"&"];

                        DatabaseManager *database = [DatabaseManager getInstance];
                        **[database addDataToTable:mcTitle title:title url:url category:cTitle];**
                    }
                    clip = clip -> nextSibling;
                }
                categ = categ -> nextSibling;
            }

            maincateg = maincateg -> nextSibling;
        }

ご覧のとおり、いくつかのネストされたループがあり、addDataToTAble(); を呼び出して各アイテムを DB に保存します。* で行を削除すると(つまり、各ループの後にアイテムを保存しない場合)、非常に高速に動作します。しかし、*の行をそのままにしておくと、とても時間がかかります。

この関数は次のとおりです。

-(void) addDataToTable: (NSString*)table
             title: (NSString*)title
               url:(NSString*)url
          category:(NSString*)category
{
    sqlite3_stmt *statement;
    const char *dbpath = [_databasePath UTF8String];

    if (sqlite3_open(dbpath, &_yunatubeDB) == SQLITE_OK) {

        NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO %@ (TITLE, URL, CATEGORY) VALUES (\"%@\", \"%@\", \"%@\")", table, title, url, category];

        const char *insert_stmt = [insertSQL UTF8String];
        sqlite3_prepare_v2(_yunatubeDB, insert_stmt,
                           -1, &statement, NULL);
        if (sqlite3_step(statement) == SQLITE_DONE) {
            //            NSLog(@"Successfully added to DB");
        } else {
            NSLog(@"Failed to add data to DB");
        }
        sqlite3_finalize(statement);
        sqlite3_close(_yunatubeDB);
    }
}

この機能は、アイテムごとの収納に時間がかかるようで、収納時間が積み重なるため、最終的には最大20秒かかる。Android にも同様のアルゴリズムを使用していますが、高速に動作しますが、ios でなぜそんなに時間がかかるのかわかりません。この処理時間は、アプリ ストアでのアプリ レビューに悪影響を及ぼすのではないかと思います。私はAndroidでも同様の方法を使用していますが、そこでは非常に高速に動作します..4秒未満です。iOSでなぜそんなに時間がかかるのかわかりません。私は何か間違っていますか?

どんな助けでも大歓迎です!

4

2 に答える 2

1

ループの前に SQLite トランザクションを開始し、後で終了してみてください。トランザクションを手動で開始/停止しない場合、SQLite は書き込みのたびに自動的にそれを行いますが、これは非常に遅くなります。

于 2013-06-23T06:36:42.783 に答える
0

20 秒あれば Apple のレビューに合格するかもしれませんが、アプリの良いレビューを得ることはできません。

エントリを見つけるたびに db に書き込みます。解析の最後に db に書き込む必要があります。

于 2013-06-23T06:37:23.583 に答える