0

Web サーバー内の xml ファイルからコンテンツをロードする UITableView があります。

  • TableView はタブ バー コントローラー内にあります。
  • ;[table reloadData]の中で呼び出します。TBXMLSuccessBlock
  • 問題は、TableView の内容が更新されないことです。
  • TBXML ライブラリを使用しています。

ボタンをクリックした後、XML ファイルがダウンロードされたことを tableView に通知して表示するにはどうすればよいですか?

- (IBAction)leftButton:(UIButton *)sender {
    if (a<=2 && a != 0) {
        a = a - 1;

        NSString *leftURL = self.getDate;
        [self loadURL:leftURL];
    }

}

- (void)loadURL:(NSString *)newURL{

    if (newURL == NULL) {
        newURL = self.getDate;
    }

    // Create a success block to be called when the asyn request completes
    TBXMLSuccessBlock successBlock = ^(TBXML *tbxmlDocument) {
        NSLog(@"PROCESSING ASYNC CALLBACK");

        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        // If TBXML found a root node, process element and iterate all children
        if (tbxmlDocument.rootXMLElement)
        {
            // Obtain root element
            TBXMLElement * root = tbxml.rootXMLElement;
        if (root)
        {
            _storeArray = [NSMutableArray new];
            TBXMLElement * elem_PLANT = [TBXML childElementNamed:@"news" parentElement:root];
            while (elem_PLANT !=nil)
            {
                TBXMLElement * elem_title = [TBXML childElementNamed:@"title" parentElement:elem_PLANT];
                NSString *titleName = [TBXML textForElement:elem_title];

                TBXMLElement * elem_artist = [TBXML childElementNamed:@"text" parentElement:elem_PLANT];
                NSString *artistName = [TBXML textForElement:elem_artist];

                TBXMLElement * elem_thumb = [TBXML childElementNamed:@"thumb_url" parentElement:elem_PLANT];
                NSString *thumbName = [TBXML textForElement:elem_thumb];

                NSDictionary *dictionary = [[NSDictionary alloc]initWithObjects:@[titleName, artistName, thumbName] forKeys:@[@"title", @"text", @"thumb"]];
                elem_PLANT = [TBXML nextSiblingNamed:@"news" searchFromElement:elem_PLANT];
                [_storeArray addObject:dictionary];

            }

        }

          [_tableView reloadData];
        }
    };

    // Create a failure block that gets called if something goes wrong
    TBXMLFailureBlock failureBlock = ^(TBXML *tbxmlDocument, NSError * error) {
        NSLog(@"Error! %@ %@", [error localizedDescription], [error userInfo]);
    };

    // Initialize TBXML with the URL of an XML doc. TBXML asynchronously loads and parses the file.
    tbxml = [[TBXML alloc] initWithURL:[NSURL URLWithString:newURL]
                               success:successBlock
                               failure:failureBlock];
}

編集: buttonClick 内の ReloadData

- (IBAction)leftButton:(UIButton *)sender {
    if (a<=2 && a != 0) {
        a = a - 1;

        NSString *leftURL = self.getDate;
        [self loadURL:leftURL];
        [_tableView reloadData];
    }

    }

- (IBAction)rightButton:(UIButton *)sender {
    if (a<2) {
        a = a + 1;
        NSString *rightURL = self.getDate;
        [self loadURL:rightURL];
        [_tableView reloadData];
    }
}

アプリの起動時: - URL 番号 1 が読み込まれます。- URL 番号 1 が表示されます。右に 1 回クリックすると: - URL 番号 2 が読み込まれます。- 何も起こりません。もう一度右クリックすると: - URL 番号 3 が読み込まれます。- URL 番号 2 が表示されます。残り 1 回クリックすると: - URL 2 が読み込まれます。- URL 3 が表示されます。もう 1 回クリックすると、次のようになります。 - URL 1 が読み込まれます。- URL 2 が表示されます。

4

2 に答える 2

1

あなたが言った:

アプリの起動時: - URL 番号 1 が読み込まれます。- URL 番号 1 が表示されます。右に 1 回クリックすると: - URL 番号 2 が読み込まれます。- 何も起こりません。もう一度右クリックすると: - URL 番号 3 が読み込まれます。- URL 番号 2 が表示されます。残り 1 回クリックすると: - URL 2 が読み込まれます。- URL 3 が表示されます。もう 1 回クリックすると、次のようになります。 - URL 1 が読み込まれます。- URL 2 が表示されます。

このことから、次のことがわかります。

  1. URL/XML の読み込みは機能します。データは表示するために存在しますが、表示すべきときに表示されません。
  2. テーブルのリロードは機能します。後でボタンを押すと、以前のデータが表示されますが、別のデータが表示されます。
  3. テーブルのリロードが早すぎるため、以前の URL/XML のデータが表示されています。

あなたのボタン アクションは、(間接的に) 成功/失敗ブロックを受け取るライブラリを使用して URL 読み込み呼び出しを行っているため、大まかに何が起こっているかを次に示します。

  1. IBAction はloadUrl:、TBXML を実行する を呼び出します。initWithURL:success:failure:
  2. initWithURL:success:failure:成功ブロックと失敗ブロックを保存し、実際のネットワーク アクションを別のスレッドで (「バックグラウンドで」) 開始し、ほぼ確実にネットワーク アクションが完了する前に戻ります。
  3. IBAction は を呼び出しますreloadData
  4. その後、バックグラウンドでネットワーク アクションが終了し、成功または失敗のブロックが実行されます。

そのため、呼び出しを成功ブロックに移動するreloadDataと、XML データが処理された後にテーブルが再ロードされるようになります。

しかし、最初は次のようなエラーでクラッシュしました:

これは、セカンダリ スレッドから UIKit を呼び出した結果である可能性があります。

UIKit の呼び出し (ユーザー インターフェイスに影響を与えるメソッドの呼び出し) は、メイン スレッドで行う必要があります。ブロック コールバックを使用する一部の非同期ライブラリ (特に AFNetworking) では、この理由から、ブロック コールバックはメイン スレッドで実行されることが保証されています。TBXML では、明らかに、ブロック コールバックはバックグラウンドで実行されます。おそらく、実際のネットワーク ローディング アクションを実行したのと同じスレッドで実行されます。そのため、メインスレッドでreloadData呼び出しを行う何らかの方法が必要です。UITableView

これを行うにはいくつかの方法があります。私の最初の好みは通常、メイン スレッドで実行する操作のキューであるメイン操作キュー (mainQueueクラス メソッド onを使用して取得) を使用することです。NSOperationQueue

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [_tableView reloadData];
}];

次に、メイン オペレーション キューは、メイン スレッドでできるだけ早くブロックの実行を自動的に処理します。代わりに、まだ Objective-C/Cocoa/CocoaTouch レベルでperformSelectorOnMainThread:withObject:waitUntilDone:、テーブル ビューで使用できます。

[_tableView performSelectorOnMainThread:@selector(reloadData)
                             withObject:nil
                          waitUntilDone:NO];

(またはYES完了するまで待機します。この場合はおそらく問題ではありません)、まったく同じ効果があります。3 番目のオプションは、この場合は一般的に好まれませんが、Grand Central Dispatch を直接使用することです。

dispatch_async(dispatch_get_main_queue(), ^{
    [_tableView reloadData];
}];

NSOperationQueue(ただし、ルートやルートのような高レベルのオプションがある場合はperformSelectorOnMainThread:withObject:waitUntilDone:、この種の低レベルの C Grand Central Dispatch ルーチンの代わりに使用する必要があります。また、に変更dispatch_asyncすると、前の例でに変更しdispatch_syncた場合と同じ効果があります) .waitUntilDone:NOwaitUntilDone:YES

于 2013-03-23T00:11:29.953 に答える
-1

あなたが言っているように、メソッド reloadData を呼び出すと、テーブルビューが更新されます..問題はないと思います.タブバーコントローラーを使用せずに誰かを試してみました..タブバーコントローラーの問題が発生することがあります. ..一度試してみてください..お知らせください..または別の方法でお手伝いします.

于 2013-03-23T04:40:56.847 に答える