3

私のアプリは、JSON を使用して Rails アプリからの情報を解析します。JSON を非同期的にロードする方法を探していますが、コードが複雑なために、見つけた例をコードで動作させるのに苦労しています。JSON を非同期でロードするにはどうすればよいですか? ありがとう。

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSURL *upcomingReleaseURL = [NSURL URLWithString:@"http://obscure-lake-7450.herokuapp.com/upcoming.json"];

    NSData *jsonData = [NSData dataWithContentsOfURL:upcomingReleaseURL];

    NSError *error = nil;

    NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];

    NSArray *upcomingReleasesArray = [dataDictionary objectForKey:@"upcoming_releases"];

    //This is the dateFormatter we'll need to parse the release dates
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
    NSTimeZone *est = [NSTimeZone timeZoneWithAbbreviation:@"EST"];
    [dateFormatter setTimeZone:est];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; //A bit of an overkill to avoid bugs on different locales

    //Temp array where we'll store the unsorted bucket dates
    NSMutableArray *unsortedReleaseWeek = [[NSMutableArray alloc] init];
    NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] init];

    for (NSDictionary *upcomingReleaseDictionary in upcomingReleasesArray) {

        //We find the release date from the string
        NSDate *releaseDate = [dateFormatter dateFromString:[upcomingReleaseDictionary objectForKey:@"release_date"]];

        //We create a new date that ignores everything that is not the actual day (ignoring stuff like the time of the day)
        NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
        NSDateComponents *components =
        [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:releaseDate];

        //This will represent our releases "bucket"
        NSDate *bucket = [gregorian dateFromComponents:components];

        //We get the existing objects in the bucket and update it with the latest addition
        NSMutableArray *releasesInBucket = [tmpDict objectForKey:bucket];
        if (!releasesInBucket){
            releasesInBucket = [NSMutableArray array];
            [unsortedReleaseWeek addObject:bucket];
        }

        UpcomingRelease *upcomingRelease = [UpcomingRelease upcomingReleaseWithName:[upcomingReleaseDictionary objectForKey:@"release_name"]];
        upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"];
        upcomingRelease.release_price = [upcomingReleaseDictionary objectForKey:@"release_price"];
        upcomingRelease.release_colorway = [upcomingReleaseDictionary objectForKey:@"release_colorway"];
        upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"];
        upcomingRelease.thumb = [upcomingReleaseDictionary valueForKeyPath:@"thumb"];
        upcomingRelease.images = [upcomingReleaseDictionary objectForKey:@"images"];
        [releasesInBucket addObject:upcomingRelease];
        [tmpDict setObject:releasesInBucket forKey:bucket];
    }

    [unsortedReleaseWeek sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSDate* date1 = obj1;
        NSDate* date2 = obj2;
        //This will sort the dates in ascending order (earlier dates first)
        return [date1 compare:date2];
        //Use [date2 compare:date1] if you want an descending order
    }];

    self.releaseWeekDictionary = [NSDictionary dictionaryWithDictionary:tmpDict];
    self.releaseWeek = [NSArray arrayWithArray:unsortedReleaseWeek];

}
4

6 に答える 6

7

簡単な方法の1 つは、NSURLConnection便利なクラス メソッドを使用することsendAsynchronousRequest:queue:errorです。

次のコード スニペットは、サーバーから JSON をロードする方法の例であり、JSON を解析するバックグラウンド スレッドで完了ハンドラーが実行されます。また、推奨されるすべてのエラー チェックも実行します。

NSURL* url = [NSURL URLWithString:@"http://example.com"];
NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest addValue:@"application/json" forHTTPHeaderField:@"Accept"];
NSOperationQueue* queue = [[NSOperationQueue alloc] init];

[NSURLConnection sendAsynchronousRequest:urlRequest
                                   queue:queue
                       completionHandler:^(NSURLResponse* response,
                                           NSData* data,
                                           NSError* error)
{
    if (data) {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        // check status code and possibly MIME type (which shall start with "application/json"):
        NSRange range = [response.MIMEType rangeOfString:@"application/json"];

        if (httpResponse.statusCode == 200 /* OK */ && range.length != 0) {
            NSError* error;
            id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
            if (jsonObject) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    // self.model = jsonObject;
                    NSLog(@"jsonObject: %@", jsonObject);
                });
            } else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    //[self handleError:error];
                    NSLog(@"ERROR: %@", error);
                });
            }
        }
        else {
            // status code indicates error, or didn't receive type of data requested
            NSString* desc = [[NSString alloc] initWithFormat:@"HTTP Request failed with status code: %d (%@)",
                              (int)(httpResponse.statusCode),
                              [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]];
            NSError* error = [NSError errorWithDomain:@"HTTP Request"
                                                 code:-1000
                                             userInfo:@{NSLocalizedDescriptionKey: desc}];
            dispatch_async(dispatch_get_main_queue(), ^{
                //[self handleError:error];  // execute on main thread!
                NSLog(@"ERROR: %@", error);
            });
        }
    }
    else {
        // request failed - error contains info about the failure
        dispatch_async(dispatch_get_main_queue(), ^{
            //[self handleError:error]; // execute on main thread!
            NSLog(@"ERROR: %@", error);
        });
    }
}];

いくらか手の込んだように見えますが、IMO これは最小限であり、まだ素朴なアプローチです。他の欠点の中でも、主な問題は次のとおりです。

  • リクエストをキャンセルする可能性がありません。
  • より高度な認証を処理する方法はありません。

より洗練されたアプローチでは、NSURLConnection デリゲートを利用する必要があります。通常、サードパーティのライブラリはこの方法で実装し、NSURLConnectionリクエストとその他の関連する状態情報を のサブクラスにカプセル化しNSOperationます。このコードをテンプレートとして使用するなど、独自の実装から始めることができます。

于 2013-10-09T08:01:46.100 に答える
0
NSString *urlstr=@"http://itunes.apple.com/in/rss/topsongs/limit=25/json";
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:urlstr]];

[NSURLConnection sendAsynchronousRequest:request
                                   queue:[[NSOperationQueue alloc] init]
                       completionHandler:^(NSURLResponse* response,
                                           NSData* data, NSError* error)
{
    NSError *myError = nil;
    NSDictionary *dic1 = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];

    if (myError ==nil) {
        NSDictionary*feed =[dic1 objectForKey:@"feed"];
        NSArray*arrayofentry =[feed objectForKey:@"entry"];

        for(NSDictionary *dic2 in arrayofentry) {
            requestReply=[dic2 objectForKey:@"title"];
            [arr1 addObject:requestReply];
        }
        [self.table reloadData];
    }
}];
于 2015-04-30T14:59:28.647 に答える
0

この回答のようにデータを非同期でダウンロードします: Object-c/iOS :ASynchronous を使用して URL からデータを取得する方法は?

次に、json パーサーで実行します。

于 2013-10-09T00:54:17.810 に答える
-1

このコードを試してください:

        NSURL * inkURL = [NSURL URLWithString:@"your url"];
        NSURLRequest * request = [[NSURLRequest alloc]initWithURL:inkURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
        NSOperationQueue * queue = [[NSOperationQueue alloc]init];
        [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse * response, NSData * data, NSError * error) {
            NSData * jsonData = [NSData dataWithContentsOfURL:inkURL];
            NSDictionary * dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
            self.inkArray = [dataDictionary objectForKey:@"users"];


        }];
于 2014-03-12T07:31:58.930 に答える