[66→100] iOS開發03:從網絡加載頁學異步加載、異步加載和JSON解析

在一個互聯的時代,網絡交互是基礎功能。這里面涉及的功能有兩大塊:

  1. 互聯協議,主流就是HTTP協議了。
  2. 交換的數據格式,主流就是JSON。

在iOS系統中,如何用http協議傳輸json呢?其中涉及到的技術有:

  1. 異步加載;
  2. 網絡交互;
  3. JSON解析

關鍵技術1:異步加載

因為網絡比較耗時,不能直接在UI線程處理,所以需要另外開啟新的線程,等數據加載完成,再講數據傳輸給UI線程處理,執行UI刷新操作。iOS中有四種方式開啟新線程

  1. Pthreads
  2. NSThread
  3. GCD(Grand Central Dispatch)
  4. NSOperation

其中,Pthreads是基于C語言的,在類Unix操作系統中通用,不是面向對象的,操作復雜;NSThread是經過蘋果封裝后的,完全面向對象的,但它的生命周期還是需要我們手動管理;GCD是蘋果為多核的并行運算提出的解決方案,所以會自動合理地利用更多的CPU內核(比如雙核、四核),會自動管理線程的生命周期(創建線程、調度任務、銷毀線程),完全不需要我們管理,我們只需要告訴干什么就行,因此成為最常用的異步加載方案;NSOperation 是蘋果公司對 GCD 的封裝,完全面向對象,所以使用起來更好理解。它們具體的使用方式和區別 參考關于iOS多線程,你看我就夠了NSOprationQueue 與 GCD 的區別與選用

關鍵技術2:網絡交互

在iOS中,常見的發送網絡交互的解決方案有

  • iOS原生接口
    • NSURLConnection:用法簡單,最古老最經典最直接的一種方案
    • NSURLSession:iOS 7新出的技術,功能比NSURLConnection更加強大
    • CFNetwork:NSURL*的底層,純C語言
  • 第三方框架
    • ASIHttpRequest:外號“HTTP終結者”,功能極其強大,可惜早已停止更新
    • AFNetworking:簡單易用,提供了基本夠用的常用功能。目前比較常用,可以用CocoaPods集成(具體方法參考:構建iOS開發工作流)。

AFNetworking是一個討人喜歡的網絡庫,適用于iOS以及Mac OS X。
它構建于在NSURLConnection, NSOperation, 以及其他熟悉的Foundation技術之上。擁有良好的架構,豐富的api,以及模塊化構建方式,使得使用起來非常輕松。示例代碼:

NSURL *url = [NSURL URLWithString:@"https://gowalla.com/users/mattt.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    NSLog(@"Name: %@ %@", [JSON valueForKeyPath:@"first_name"], [JSON valueForKeyPath:@"last_name"]);
} failure:nil];
[operation start];

關鍵技術3:JSON解析

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它使得人們很容易的進行閱讀和編寫。同時也方便了機器進行解析和生成。JSON采用完全獨立于程序語言的文本格式。

  1. iOS原生接口:NSJSONSerialization
  2. 第三方框架:在github搜索json,object-c下star前三的如下

其中,JSONKit 是用 Objective-C 實現的一個高性能的 JSON 解析和生成庫,支持iOS。解析(Parsing)和序列化(Serializing)性能比較如下:



簡單實例

NetViewController用原生的GCD、NSURLConnection、NSJSONSerialization模擬了 異步加載、 網絡交互、JSON解析等功能。
NetViewController.h代碼如下:

//
//  NetViewController.h
//  PandaiOSDemo
//
//  Created by shitianci on 16/7/1.
//  Copyright ? 2016年 Panda. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface NetViewController : UIViewController

@property (strong, nonatomic)  UILabel *infoLabel;

@end

NetViewController.m代碼如下:

//
//  NetViewController.m
//  PandaiOSDemo
//
//  Created by shitianci on 16/7/1.
//  Copyright ? 2016年 Panda. All rights reserved.
//

#import "NetViewController.h"

@interface NetViewController ()

@end

@implementation NetViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.infoLabel = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.infoLabel.text = @"網絡加載中...";
//    self.infoLabel.backgroundColor = [UIColor greenColor];


    /**
     *  創建異步任務
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        //code here
        NSLog(@"這是異步任務", [NSThread currentThread]);
        
        /**
         *  訪問網絡,輸出錯誤日志
         */
        {
            NSURL *url = [[NSURL alloc] initWithString:@"http://www.xxx.xxx"];
            NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
            
            NSError *error = nil;
            NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
            if (data == nil) {
                NSLog(@"send request failed: %@", error);
            }
        }
        
        
        /**
         *  此處模擬json串,進行解析
         */
        NSString *jsonString = @"{\"jsonKey\": \"這是網絡數據中,jsonKey對應的數據\"}";
        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSString *result;
        {
            NSError *error;
            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
            if (json == nil) {
                NSLog(@"json parse failed \r\n");
            }
            result = [json objectForKey:@"jsonKey"];
        }
        
        sleep(2);
        dispatch_async(dispatch_get_main_queue(), ^{
            /**
             *  通知主線程刷新
             */
            self.infoLabel.text = result;
            
        });
      
    });

    
    [self.view addSubview:self.infoLabel];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

參考:

  1. iOS開發網絡篇—HTTP協議
  2. AFNetworking
  3. Objective-C的JSON開發包 JSONKit

Panda
2016-07-01

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容