1

API から JSON を解析し、テーブルビューに表示することに成功しました。私が受け取っているデータは、彼が登録しているユーザーのクラスですが、私が受け取っているデータはクラス ID のみであるため、各クラス ID を取得し、クラス名と教師を取得するために個別の API 要求を送信する必要があります。ユーザーが行をクリックするとクラスIDを取得できるため、別のView Controllerでこれを正常に実行できますが、クラス名と教師とIDを単一のテーブルビューに表示したいと思います。

私の質問は、テーブル ビューからデータを取得し、セルごとに個別の API 要求を作成して、そのセルにデータを表示するにはどうすればよいかということです。

私の現在のデータ:

私がこれまでに持っているもの

行をクリックすると、次のデータが得られます。

2013-06-17 17:06:59.232 App[22024:c07] Class: Honors Pre-Calculus
2013-06-17 17:06:59.233 App[22024:c07] Teacher: Joe Shmo

両方を1つの画面に表示するにはどうすればよいですか?

これは、最初の画面でクラス ID を取得するための私のコードです。

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

if ([searchResults count] == 0) {
    return [tableView dequeueReusableCellWithIdentifier:
            NothingFoundCellIdentifier];



} else {

    ScheduleResultCell *cell = (ScheduleResultCell *)[tableView dequeueReusableCellWithIdentifier:SearchResultCellIdentifier];

    ScheduleResult *searchResult = [searchResults objectAtIndex:indexPath.row];


    NSString *classFormat = @"%@";
    NSString *classfks = searchResult.class_fk;
    NSString *classfk = [NSString stringWithFormat:classFormat, classfks];

    cell.idLabel.text = classfk;

    return cell;

}
}

これは、2 番目の画面でクラス情報を取得するための私のコードです。

-(void)viewDidAppear:(BOOL)animated {
url = [NSString stringWithFormat:@"https://myapiurl.com/v1/classes/%@.json", idValue];

//show loader view
[SVProgressHUD showWithStatus:@"Loading Info"];

//fetch the feed
_feed = [[ClassFeed alloc] initFromURLWithString:url
                                      completion:^(JSONModel *model, JSONModelError *err) {

                                          //hide the loader view
                                          [SVProgressHUD dismiss];

                                          //json fetched
                                          NSLog(@"Class: %@", _feed.course);
                                          NSLog(@"Teacher: %@", _feed.teacher_full_name);
                                          NSLog(@"Meeting Info: %@", _feed.meeting_times);

                                          [self.tableView reloadData];

                                      }];

}

これを1つの画面で実現する方法はありますか?

これが私がやろうとしてきたことですが、1つのセルにしかデータが表示されないようです:

int count = [searchResults count];

    NSString *classFormat = @"%@";
    NSString *classfks = searchResult.class_fk;
    NSString *classfk = [NSString stringWithFormat:classFormat, classfks];

    for (int i=0; i < count; i++) {
        ScheduleResult *classInfo = [searchResults objectAtIndex:indexPath.row];
        NSString *classId = classInfo.class_fk;
        NSLog(@"i value: %d", i);
        url2 = [NSString stringWithFormat:@"https://apiurl.com/v1/classes/%@.json", classId];
        NSLog(@"url value: %@", url2);
        [SVProgressHUD showWithStatus:@"Loading Info"];
        _feed = [[ClassFeed alloc] initFromURLWithString:url2
                                              completion:^(JSONModel *model, JSONModelError *err) {

                                                  //hide the loader view
                                                  [SVProgressHUD dismiss];

                                                  //json fetched
                                                  NSLog(@"Class #%d: %@", i, _feed.course);
                                                  NSLog(@"Teacher #%d: %@", i,  _feed.teacher_full_name);
                                                  NSLog(@"Meeting #%d: %@", i,  _feed.meeting_times);
                                                  //name = namefk;
                                                  NSString *nameFormat = @"%@";
                                                  NSString *namefks = _feed.course;
                                                  NSString *namefk = [NSString stringWithFormat:nameFormat, namefks];
                                                  cell.nameLabel.text = namefk;

                                                  //[self.tableView reloadData];

                                              }];



                }

別の方法でデータを配列に追加しようとしましたが、それを正しく達成することさえできません。

NSMutableArray* fullArray;
    fullArray = [[NSMutableArray alloc] init];
    [fullArray addObject:classfk];
    NSLog(@"array: %@", fullArray);

デバッグ出力:

array: ( 10326
) 2013-06-17 23:36:45.488 App[30088:c07] array: ( 10371 ) 
2013-06-17 23:36:45.494 App[30088:c07] array: (
10420 )

この質問があまり意味をなさない場合は、この JSON フィード (最初の URL) から class_fk を取得する方法をお尋ねしたいと思います。

[{
    "class_fk": 10326,
    "currently_enrolled": true,
    "date_withdrawn": null,
    "enrollment_pk": 147745,
    "fee_paid": false,
    "late_date_enrolled": null,
    "level": null,
    "student_fk": 132664,
    "update_date": "2012-08-27"
},
{
    "class_fk": 10371,
    "currently_enrolled": true,
    "date_withdrawn": null,
    "enrollment_pk": 147168,
    "fee_paid": false,
    "late_date_enrolled": null,
    "level": null,
    "student_fk": 132664,
    "update_date": "2012-08-23"
}

それを使用して別の URL に挿入し、これからコースと teacher_full_name を取得しますか? (2 番目の URL):

{
"class_id": "ADVMTG-40",
"class_pk": 10326,
"course": "Advisor Meeting",
"course_id": 7,
"course_type": "Advisory",
"description": "ADV: Shmo, J.",
"group_fk": 13980,
"primary_grade_level": "None",
"school_level": "Upper School",
"school_year": 2012,
"status": "Active",
"subject": "Administration",
"teacher_fk": 80404,
"teacher_full_name": "Joe Shmo",
"update_date": "2012-10-23T10:06:00-05:00",
"teachers": [
    {
        "person_fk": 80404,
        "role": "Primary Teacher",
        "role_id": 1,
        "teacher_name": "Joe Shmo",
        "update_grades": true,
        "view_grades": true
    }
],
"meeting_times": [
    {
        "block": "Advisor Meetings",
        "block_abbreviation": "ADV",
        "day": "Friday",
        "end_time": null,
        "grading_period": "ALL",
        "room": null,
        "start_time": null
    }
]}

これが私の問題の解決策です(助けてくれてありがとう!):

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{



    //[searchResults sortUsingSelector:@selector(compareName:)];

    NSString *urlString = @"https://apiurl.com/v1/enrollments.json?student=132664";
    NSURL *Url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:Url];
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSArray *classes = [NSJSONSerialization JSONObjectWithData:data
                                                       options:NSJSONReadingMutableContainers
                                                         error:nil];
    //NSLog(@"classes array: %@", classes);

    //now we loop through all classes
    for (NSMutableDictionary *class in classes) {

        //we get individual data for each class

        NSString *classID = class[@"class_fk"];
        //NSLog(@"classID: %@", classID);
        NSString *classUrlString = [NSString stringWithFormat:@"https://apiurl.com/v1/classes/%@.json", classID];
        NSURL *classUrl = [NSURL URLWithString:classUrlString];
        NSURLRequest *classRequest = [NSURLRequest requestWithURL:classUrl];


        NSData *classData = [NSURLConnection sendSynchronousRequest:classRequest returningResponse:nil error:nil];
        NSDictionary *classDictionary = [NSJSONSerialization JSONObjectWithData:classData
                                                                        options:NSJSONReadingMutableContainers
                                                                          error:nil];
        //NSLog(@"classes dictionary: %@", classDictionary);
        if (classes == nil) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self showNetworkError];
            });
            return;

        } else {
            if (classDictionary == nil) {
                NSLog(@"classes dictionary: %@", classDictionary);
            } else {
        //probably should check here if array is empty before accessing first object
        //we shove the data from a classDictionary into class
        //class[@"teacher_full_name"] = classDictionary[@"teacher"][0];

                if (classDictionary[@"teacher_full_name"] == nil) {
                    class[@"teacher_full_name"] = @"Not Provided";
                } else {
                    class[@"teacher_full_name"] = classDictionary[@"teacher_full_name"];
                }

                if (classDictionary[@"course"] == nil) {
                    class[@"course"] = @"Not Provided";
                } else {
                    class[@"course"] = classDictionary[@"course"];
                }

                if (classDictionary[@"class_pk"] == nil) {
                    class[@"class_pk"] = @"Not Provided";
                } else {
                    class[@"class_pk"] = classDictionary[@"class_pk"];
                }

                if (classDictionary[@"teachers"][0][@"person_fk"] == nil) {
                    class[@"person_fk"] = @"Not Provided";
                } else {
                 class[@"person_fk"] = classDictionary[@"teachers"][0][@"person_fk"];   
                }

        ScheduleResult *searchResult = [[ScheduleResult alloc] init];
        searchResult.name = class[@"course"];
        searchResult.teacher = class[@"teacher_full_name"];
        searchResult.class_fk = class[@"class_pk"];

        [searchResults addObject:searchResult];


        NSLog(@"searchresult: %@", class[@"person_fk"]);
        //NSLog(@"course: %@ and teacher: %@", class[@"course"], class[@"teacher_full_name"] );
            }
        }

    }



    dispatch_async(dispatch_get_main_queue(), ^{
        //NSLog(@"dictionary: %@", classes);
        [self.tableView reloadData];
        [SVProgressHUD dismiss];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    });
4

1 に答える 1

2

ここには 2 つのオプションがあります。

まず、(バックグラウンド キューで) 最初のフィードを取得します。次に、JSON を解析します。次に、JSON をループし、配列内の各辞書に対して API 呼び出しを行い、それを辞書に押し戻します。次に、テーブルにメイン キューをリロードするように指示します。

2 番目のオプションはもう少し複雑です。ユーザーがテーブルをスクロールすると、バックグラウンド キューで呼び出しを行い、適切なデータを取得してセルを更新できます。これは、画像がセルに非同期的に読み込まれる方法と非常によく似ています。ここを除いて、これは画像ではなく JSON です。これが 2 回発生しないように、このデータをキャッシュする必要があります。また、ユーザーのスクロールが速すぎて、データをロードしているセルが画面に表示されなくなった場合は、リクエストをキャンセルする必要があります。

最初のものにとどまることをお勧めします。シンプルで簡単に保つことをお勧めします(ただし、事前にデータを熱心にロードするため、効率的ではないかもしれませんが、最初の API 呼び出しによって返されるレコードの数が少ない場合は、問題ないはずです、ただし、100 秒の場合は 2 番目のオプションを使用します)。

また、最初のオプションではすべての操作を同期的に実行する必要があることに注意することも重要です (これにより、すべてのデータがダウンロードされたことがわかります)。

これが最初のオプションです。これは NSURLConnection で行いました。私はこのオプションが好きではないことに注意してください。しかし、それは簡単で仕事を終わらせます:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        //first we get all classes
        NSString *urlString = @"https://myapiurl.com/v1/classes";
        NSURL *url = [NSURL URLWithString:urlString];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        NSArray *classes = [NSJSONSerialization JSONObjectWithData:data
                                                           options:NSJSONReadingMutableContainers
                                                             error:nil];

        //now we loop through all classes
        for (NSMutableDictionary *class in classes) {

            //we get individual data for each class

            NSString *classID = class[@"class_fk"];
            NSString *classUrlString = [NSString stringWithFormat:@"https://apiurl.com/v1/classes/%@.json", classID];
            NSURL *classUrl = [NSURL URLWithString:classUrlString];
            NSURLRequest *classRequest = [NSURLRequest requestWithURL:classUrl];


            NSData *classData = [NSURLConnection sendSynchronousRequest:classRequest returningResponse:nil error:nil];
            NSDictionary *classDictionary = [NSJSONSerialization JSONObjectWithData:classData
                                                                            options:NSJSONReadingMutableContainers
                                                                              error:nil];

            //probably should check here if array is empty before accessing first object
            //we shove the data from a classDictionary into class
            class[@"teachers_name"] = classDictionary[@"teachers"][0];
            class[@"course"] = classDictionary[@"course"];

        }

        //now you've got an array of dictionaries that have teachers name and course in it.
        //we tell our tableview to reload the data on main queue
        dispatch_async(dispatch_get_main_queue(), ^{
            [someTableView reloadData];
        });
    });
于 2013-06-18T04:06:53.127 に答える