gpt4 book ai didi

ios - 如何异步加载 JSON (iOS)

转载 作者:可可西里 更新时间:2023-11-01 17:08:11 24 4
gpt4 key购买 nike

我的应用使用 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];

}

最佳答案

一种简单的方法是使用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);
});
}
}];

尽管它看起来有些复杂,但在我看来,这是一种极简主义且仍然天真的方法。除其他缺点外,主要问题是:

  • 它没有取消请求的可能性,并且
  • 没有办法处理更复杂的身份验证。

更复杂的方法需要利用 NSURLConnection 委托(delegate)。通常,第三方库确实以这种方式实现它,将 NSURLConnection 请求和其他相关状态信息封装到 NSOperation 的子类中。你可以从你自己的实现开始,例如使用 this code作为模板。

关于ios - 如何异步加载 JSON (iOS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19261081/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com