如何异步加载 JSON (iOS)

2023-12-31

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

}

One simple方法是使用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 代表们。通常,第三方库确实以这种方式实现它,封装了NSURLConnection请求和其他相关状态信息放入子类中NSOperation。您可以从自己的实现开始,例如使用这段代码 https://gist.github.com/couchdeveloper/5764723作为模板。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何异步加载 JSON (iOS) 的相关文章

  • React Native facebook iOS sdk 构建失败

    我已遵循 Facebook 开发人员指南中列出的 iOS React Native sdk 的所有准则 但我仍然无法构建该应用程序 附上我的配置和构建日志的屏幕截图 Ld Users alaaattya Library Developer
  • 如何在 Swift 中“生成”闭包类型别名?

    为了使我的代码更易于阅读 我在 Swift 中对各种类型的闭包使用类型别名 我有以下基本的闭包集 public typealias FailureClosure error NSError gt Void public typealias
  • Swift - 我可能已经删除了 Apple Swift Packages 集合

    我对 swift 和 XCode 很陌生 昨天我正在开发一个项目 想尝试一下某人制作的自定义日期选择器 所以我转到 添加包 并粘贴 GitHub 链接并添加它 我已经在我的项目中添加了一个名为 KeychainAccess 的不同包 方式
  • JSON GSON.fromJson Java 对象

    我正在尝试将 Json 加载到我的班级中 public User this fbId 0 this email this name this thumb this gender this location this relationship
  • iOS 应用程序测试。应用程序安装失败。找不到代码签名[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我尝试在多个 iOS 设备上安装我的应用程序 但这件事不让我这么做 我想知道 问题是什么以及我应该如何解决它 就我而言
  • iOS 和 Firebase 自动续订订阅

    我的问题 我很难找到一种使用 Firebase 在 iOS 中安全管理自动续订订阅的方法 购买流程 User1 purchases a subscription 使用订阅标识符更新 Firebase 上 User1 的帐户 用于解锁内容 存
  • MySQL 与 PostgreSQL JSON 搜索功能

    我一直在寻找一篇博客文章或一个功能矩阵 通过 JSON 功能对 MySQL 和 PostgreSQL 进行比较 我找到了一个好的Postgres 的特征矩阵 https www postgresql org about featuremat
  • 如何在 MySQL 查询本身中检索 JSON 数组中存储的值?

    我有下表 product id product name image path misc 1 flex http firstpl course level id 19 group id 40067 2 Android http firstp
  • 如何在ios开发中从mp3文件中提取元数据

    我正在开发一个带有云存储的 ios 音乐播放器 我需要提取音乐信息 如标题 艺术家 艺术作品 我有一个名为 playit 的操作 可以播放和暂停 mp3 文件 它还应该使用与 mp3 文件关联的元数据来填充一些 UILables 和 UII
  • 如何在 Alamofire 中使用“responseDecodable”方法?

    I have been trying to use responseDecodable method from Alamofire but I m getting Generic parameter T could not be infer
  • Pinterest 身份验证 url 返回 404 错误?

    我正在测试 pinterest apihttp pinterest com developers api http pinterest com developers api 在上面的身份验证部分的网址上 它说我必须将用户重定向到 pinte
  • 核心数据executeFetchRequest消耗大量内存

    我正在核心数据数据库中插入 cca 100 000 条记录 数据库包含 3 个实体 球员 俱乐部 球员俱乐部 实体之间存在关系 玩家 gt 玩家俱乐部俱乐部 在 PlayerClub 中插入时 我注意到插入大约 50 000 条记录后会消耗
  • 如何在禁用状态下更改 UIButton 图像 alpha?

    我有一个带有图像的 UIButton 在其禁用状态下 该图像应具有 0 3 alpha UIButton button UIButton buttonWithType UIButtonTypeCustom UIImage arrowImag
  • 我的 iPhone 6 获取 iPhone 5 媒体查询

    我不明白这里发生了什么事 我在 CSS 媒体查询中专门针对 iphone 5 media only screen and min device width 320px and max device width 568px some div
  • -[_SwiftValueencodeWithCoder:]:无法识别的选择器发送到实例

    尝试使用 NSCoder 时出现错误 玩家 swift class Player NSObject NSCoding private var playerName String private var playerScore Int pri
  • Polymer core-ajax 不会发布 JSON?

    我正在使用 core ajax 来检索 JSON 数据 将组件翻转为 JSON 格式回传到服务器则完全是另一回事 在所有情况下 无论传入的 contentType 或 handleAs 参数如何 作为输入传入的 JSON 对象似乎都会被转换
  • 如何动态添加XCTestCase

    我正在为一个白标签项目编写 UI 测试 其中每个应用程序都有一组不同的菜单项 测试点击每个菜单项并截取屏幕截图 使用快车道快照 https docs fastlane tools actions snapshot 目前这一切都发生在一个内部
  • ios swift 如何将默认语言设置为阿拉伯语?

    我正在开发一个有两种语言的应用程序 即英语和阿拉伯语 我用英语编写了该应用程序 然后用阿拉伯语本地化了该应用程序 更改语言时需要重新启动应用程序 我唯一的问题是 第一次安装应用程序时如何将默认语言设置为阿拉伯语 我尝试在编辑方案部分将语言设
  • 为什么我收到 com.facebook.sdk.login 错误 308?

    我正在使用 Xcode 7 0 在 iOS 9 0 2 上进行测试并使用 Facebook SDK 4 7 0 当我登录用户时 大多数时候一切都正常 但有时我不断收到此错误 但我不知道为什么 操作无法完成 com facebook sdk
  • 在启动屏幕中执行代码已更新

    在原始启动屏幕中执行代码 https stackoverflow com questions 27642016 execute code in launch screen 现在默认的LaunchScreenXcode 项目中的文件已更改为

随机推荐