2

UITableViewController があります。

「ut」が常に異なる URL ( http://webservices.company.nl/api?station=ut ) を (駅ごとに) 複数回呼び出したい(駅のコード)。そして、結果を毎回新しいテーブルビュー行に入れたいと思っています。(URL は XML を返します)。

URL を呼び出すには、これを使用します。

                // Create connection
                NSURLConnection *urlConnection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://webservices.company.nl/api?station=%@", station.stationCode]]] delegate:self];
                [urlConnection start];

次に、「connectionDidFinishLoading」で、NSXMLParser を使用して URL コンテンツを解析するためにこれを使用しました。

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:receivedDataFromURL];
[parser setDelegate:self];
[parser parse];
}

「didStartElement」、「didEndElement」などのすべてのメソッドを実装しましたが、ファイル内のすべての要素を正常に読み取ることができました。

私の質問:

テーブルビューのすべての行に対してこれを行う最良の方法は何ですか?また、結果をすべての行に入れるにはどうすればよいですか? 私はこれを非同期にしたいので、これに最適な構造が何であるかわかりません。

よろしくお願いします。

4

2 に答える 2

2

ここでのパターンは、画像の遅延読み込みのようなものです。

1) TrainStation のようなカスタム オブジェクトを作成します。これには、NSString 駅コード、呼び出し元に Web サービスから初期化されたことを伝える関数の BOOL プロパティ、およびブロック完了ハンドラーを提供する init メソッドが必要です。

// TrainStation.h
@interface TrainStation : NSObject

@property (strong, nonatomic) NSString *stationCode;  // your two character codes
@property (strong, nonatomic) id stationInfo;  // stuff you get from the web service
@property (strong, nonatomic) BOOL hasBeenUpdated;
@property (copy, nonatomic) void (^completion)(BOOL);

- (void)updateWithCompletion:(void (^)(BOOL))completion;
@end

2) 完了ハンドラーは NSURLConnection を開始し、後で解析が完了したときに完了ブロックを保存します...

// TrainStation.m
- (void)updateWithCompletion:(void (^)(BOOL))completion {

    self.completion = completion;
    NSURL *url = // form this url using self.stationCode
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

    [NSURLConnection sendAsynchronousRequest:self queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    }];
}

// TrainStation does it's own parsing, then
- (void)parserDidEndDocument:(NSXMLParser *)parser

    self.hasBeenUpdated = YES;
    self.completion(YES);
    // when you hold a block, nil it when you're through with it
    self.completion = nil;
}

3) テーブルを含むビュー コントローラーは、スクロールに応じてテーブルビュー セルが好きなように行き来することを認識する必要があるため、Web 結果の唯一の安全な場所はモデル (TrainStations の配列) です。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // normal stuff, dequeue cell, etc.

    // the interesting part

    TrainStation *trainStation = self.array[indexPath.row];
    if ([trainStation hasBeenUpdated]) {
        cell.detailTextLabel.text = [trainStation.stationInfo description];
        // that's just a shortcut.  teach your train station how to produce text about itself
    } else { // we don't have station info yet, but we need to return from this method right away
        cell.detailTextLabel.text = @"";
        [trainStation updateWithCompletion:^(id parse, NSError *) {
            // this runs later, after the update is finished.  the block retains the indexPath from the original call
            if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) {
                // this method will run again, but now trigger the hasBeenUpdated branch of the conditional
                [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
            }
        }];
    }
    return cell;
}
于 2013-08-14T00:55:03.237 に答える