在一個互聯的時代,網絡交互是基礎功能。這里面涉及的功能有兩大塊:
- 互聯協議,主流就是HTTP協議了。
- 交換的數據格式,主流就是JSON。
在iOS系統中,如何用http協議傳輸json呢?其中涉及到的技術有:
- 異步加載;
- 網絡交互;
- JSON解析
關鍵技術1:異步加載
因為網絡比較耗時,不能直接在UI線程處理,所以需要另外開啟新的線程,等數據加載完成,再講數據傳輸給UI線程處理,執行UI刷新操作。iOS中有四種方式開啟新線程
- Pthreads
- NSThread
- GCD(Grand Central Dispatch)
- 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采用完全獨立于程序語言的文本格式。
- iOS原生接口:NSJSONSerialization
- 第三方框架:在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
參考:
Panda
2016-07-01