IOS——網絡編程

基本概念:php

客戶端(Client):移動應用(iOS,Andorid等應用)
服務器(Server):爲客戶端提供服務、提供數據、提供資源的機器
請求(Request):客戶端向服務器索取數據的⼀種行爲
響應(Response):服務器對客戶端的請求作出的反應,⼀般指返回數據給客戶端html

##一、URLgit

1.基本介紹github

URL的全稱是Uniform Resource Locator(統⼀資源定位符) 經過1個URL,能找到互聯⺴上惟一的1個資源json

URL就是資源的地址、位置,互聯網上的每一個資源都有一個惟一的URLapi

URL的基本格式 = 協議://主機地址/路徑 http://61.144.56.195/forum/201302/19/144736txfrcuyvmustucmv.jpg http://www.fzlu.com/uploads/allimg/140107/1-14010G22134235.jpg瀏覽器

協 議:不一樣的協議表明不一樣的資源查找方式、資源傳輸方式緩存

主機地址:存放資源的主機的IP地址(域名)安全

路 徑:資源在主機中的具體位置服務器

2.URL中常見的協議

a.HTTP:超文本傳輸協議,訪問的是遠程的⺴絡資源,格式是http:// http協議是在網絡開發中最經常使用的協議

b.file:訪問的是本地計算機上的資源,格式是file://(不用加主機地址)

c.mailto:訪問的是電子郵件地址,格式是mailto:

d.FTP:訪問的是共享主機的⽂文件資源,格式是ftp://

##二、HTTP協議

1.HTTP協議簡介 不論是移動客戶端仍是PC端,訪問遠程的⺴絡資源常用HTTP協議

訪問百度主⻚頁:http://www.baidu.com 得到新浪的微博數據 得到⼤大衆點評的團購數據

2.HTTP協議的做用

HTTP的全稱是Hypertext Transfer Protocol,超⽂本傳輸協議

(1)規定客戶端和服務器之間的數據傳輸格式

(2)讓客戶端和服務器能有效地進行數據溝通

##三、HTTP通訊過程:請求和響應

1.HTTP請求

HTTP協議規定,1個完整的由客戶端發給服務器的HTTP請求中包含如下內容

  • 請求行:包含了請求方法、請求資源路徑、HTTP協議版本 GET /MJServer/resources/images/1.jpg HTTP/1.1

  • 請求頭:包含了對客戶端的環境描述、客戶端請求的主機地址等信息

  • Host: 192.168.1.105:8080 // 客戶端想訪問的服務器主機地址

  • User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客戶端的 類型,客戶端的軟件環境

  • Accept: text/html, /// 客戶端所能接收的數據類型 Accept-Language: zh-cn // 客戶端的語言環境

  • Accept-Encoding: gzip // 客戶端支持的數據壓縮格式 請求體:客戶端發給服務器的具體數據,好比文件數據

2.HTTP響應

客戶端向服務器發送請求,服務器應當作出響應,即返回數據給客戶端

HTTP協議規定:1個完整的HTTP響應中包含如下內容:

狀態行:包含了HTTP協議版本、狀態碼、狀態英⽂名稱HTTP/1.1 200 OK
響應頭:包含了對服務器的描述、對返回數據的描述 Server: Apache-Coyote/1.1 // 服務器的類型
Content-Type: image/jpeg // 返回數據的類型
Content-Length: 56811 // 返回數據的長度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 響應的時間 實體內容:服務器返回給客戶端的具體數據,⽐好比⽂件數據

3.HTTP常見狀態響應碼

狀態碼 英文名稱 中文描述
200 OK 請求完成
400 Bad Request 客戶端請求的語法錯誤,服務器沒法解析
404 Not Found 服務器沒法根據客戶端的請求找到資源
500 Internal Server Error 服務器內部錯誤,沒法完成請求

##四、發送HTTP請求的方法 1.簡單說明

在HTTP/1.1協議中,定義了8種發送http請求的⽅方法 GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH 根據HTTP協議的設計初衷,不一樣的⽅法對資源有不一樣的操做⽅式
PUT :增
DELETE :刪
POST:改
GET:查
提示:最經常使用的是GET和POST(實際上GET和POST都能辦到增刪改查)

2.get和post請求

要想使⽤GET和POST請求跟服務器進⾏交互,得先了解一個概念:參數就是傳遞給服務器的具體數據,好比登陸時的賬號、密碼

GET:在請求URL後面以?的形式跟上發給服務器的參數,多個參數之間用&隔開, ⽐如http://ww.test.com/login?username=123&pwd=234&type=JSON(因爲瀏覽器和 服務器對URL長度有限制,所以在URL後面附帶的參數是有限制的,一般不能超過1KB)

POST:發給服務器的參數所有放在請求體中(POST傳遞的數據量沒有限制)

3.get和post的選擇

(1)若是要傳遞⼤量數據,⽐如文件上傳,只能用POST請求
(2)GET的安全性比POST要差些,若是包含機密\敏感信息,建議用POST (3)若是僅是索取數據(數據查詢),建議使用GET
(4)若是是增長、修改、刪除數據,建議使⽤POST

1.基本流程

  • 構造NSURL實例(地址)
  • ⽣成NSURLRequest請求(網絡請求的信息)
  • 經過NSURLConnection發送請求
  • 經過返回NSURLRespond實例和NSError實例分析結果
  • 處理返回數據

同步GET請求、同步POST請求,異步GET請求,異步POST請求

##六、GET請求

GET請求:獲取數據,把參數以URL的形式拼接傳給服務器,以 ? 分開URL地址和參數,& 拼接多個參數

1.建立一個URL

NSString *urlStr = @"https://route.showapi.com/213-4?showapi_appid=24110&showapi_timestamp=20160905154834&topid=5&showapi_sign=5d1ba1725827501e32238072e5960958";
    
    NSURL *URL = [NSURL URLWithString:urlStr];

2.建立一個NSURLRequest 請求

NSURLRequest *request = [NSURLRequest requestWithURL:URL];

三、建立NSURLSession

NSURLSession *session = [NSURLSession sharedSession];

四、由session建立一個請求數據的任務NSURLSessionDataTask,(會以異步的形式發送網絡請求,不會阻塞主線程)

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 執行完後 以block 返回結果,解析數據
        NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        
        NSLog(@"%@",jsonData);
        
    }];

五、開始執行網絡任務

[dataTask resume];

##七、POST請求

POST請求時要指明請求的方式HTTPMethod 爲 POST,參數以請求體 HTTPMethod 的形式傳入。

一、設置請求方式爲 POST

NSURL *url = [NSURL URLWithString:@"https://route.showapi.com/213-4"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
   
    request.HTTPMethod = @"POST";

二、設置請求體:把參數做爲NSData類型傳入

NSString *parmStr = [NSString stringWithFormat:@"showapi_appid=%@&showapi_timestamp=%@&topid=%@&showapi_sign=%@",APPID,@"20160905154834",@"5",SIGN];
       
    request.HTTPBody = [parmStr dataUsingEncoding:NSUTF8StringEncoding];

3.建立一個NSURLRequest 請求

NSURLSession *session = [NSURLSession sharedSession];

四、由session建立一個請求數據的任務NSURLSessionDataTask,(會以異步的形式發送網絡請求,不會阻塞主線程)

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if (error) {
            NSLog(@"%@",error);
            return;
        }        
        // NSLog(@"%@",response);
        
        // 執行完後 以block 返回結果,解析數據
        NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        
        NSLog(@"%@",jsonData);        
    }];
    
    [dataTask resume];

###7.1 網絡請求配置

設置緩存策略:cachePolicy

NSURLRequestUseProtocolCachePolicy = 0, // 默認,使用緩存,當下一次請求時先判斷是否有緩存,有就使用緩存沒有才進行網絡請求,使用緩存時會先判斷緩存是否過時,過時的就從新請求網絡。
     NSURLRequestReloadIgnoringLocalCacheData = 1, // 忽略緩存,不使用緩存
     NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // 無視任何的緩存策略,不管是本地的仍是遠程的,老是從原地址從新下載  
     NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
     
     NSURLRequestReturnCacheDataElseLoad = 2, 首先使用緩存不論是否過時,若是沒有本地緩存,才從原地址下載
     
     NSURLRequestReturnCacheDataDontLoad = 3, 使用本地緩存,從不下載,若是本地沒有緩存,則請求失敗。此策略多用於離線操做
     
     NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented

timeoutInterval: 設置請求超時的時間秒數

NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10];

NSURLSessionConfiguration:配置網絡請求

defaultSessionConfiguration, 默認的模式,能夠緩存數據
     ephemeralSessionConfiguration, 無痕瀏覽,不會有任何的緩存
     backgroundSessionConfigurationWithIdentifier
   
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

經過 NSURLSessionConfiguration 設置緩存策略

configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

###7.2 下載數據

在實際應用中咱們常常須要知道下載的進度,咱們能夠經過block和NSURLSessionDownloadDelegate代理兩種方式來實現這點,

當咱們不須要監聽下載數據進度的時候就能夠用block方式 block方式:

建立URL

NSURL *url = [NSURL URLWithString:@"http://dl.stream.qqmusic.qq.com/108051051.mp3?vkey=4A95A0FCDFDC050E9D543841CA4A28AABD19F1973177DAB509EEBED09344D0A91A286D0800E7C58751A670CC429DB1118C98F8908C487284&guid=2718671044"];

建立Session並設置

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

建立一個下載任務

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if (error) {
            return;
        }
        
        // 二、設置保存文件的本地URL
        NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        //拼接一個數據名,response suggestedFilename 自動獲取下載數據的名字.格式類型
        NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:[response suggestedFilename]];
        
        NSError *moveError = nil;
        // 三、將下載的數據從臨時URL移動到指定的URL
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError];
        if (!moveError) {
            
            NSLog(@"保存成功");
        }
        
        NSLog(@"%@",location);
        
    }];

啓動下載

[downloadTask resume];

當咱們須要監聽下載進度的時候就用代理 代理方式

簽定協議

@interface ViewController ()<NSURLSessionDownloadDelegate>

配置NSURLSession並設置代理,delegateQueue:代理執行的線程

NSURL *url = [NSURL URLWithString:@"https://github.com/AFNetworking/AFNetworking/archive/master.zip"];
    
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSURLSessionDownloadTask *downTask = [session downloadTaskWithURL:url];
    
    [downTask resume];

監聽下載進度

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    // bytesWritten: 時間點下載的數據大小 totalBytesWritten:已經下載的數據大小,totalBytesExpectedToWrite: 下載文件的總大小
    
    self.prograssView.prograss = (CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite;
    
    NSLog(@"%lld, %lld, %lld ",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}

下載完成後調用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    
    NSLog(@"下載完成 %@",NSHomeDirectory());
    
    // 一、設置保存文件的本地URL
    NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:downloadTask.response.suggestedFilename];
    
    NSError *moveError = nil;
    // 二、將下載的數據從臨時URL移動到指定的URL
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError];
    if (!moveError) {
        
        NSLog(@"保存成功");
    }
}

###7.3 上傳數據

上傳數據用POST方式上傳 上傳數據也有block和代理兩種方式

block方式 建立URL,可變請求,請求類型爲Post

NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];
    request.HTTPMethod = @"POST";

設置請求頭的上傳文件的內容格式(Content-Type) 爲圖片類型(image/jpeg)、()

[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];

設置請求頭的響應(Accept)的文本格式(text/html)

[request setValue:@"text/html" forHTTPHeaderField:@"Accept"];
    
    NSURLSession *session  = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

上傳方式一:把要上傳的數據保存爲NSData

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5);
     
     NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
     
     if (error) {
     NSLog(@"%@",error);
     
     } else {
     
     NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
     
     NSLog(@"%@ \n%@",response, reuslt);
     }
     
     }];

上傳方式二:使用文件所在的本地的URL

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"image7" withExtension:@"jpeg"];
    
    // NSURL *fileURL = [NSURL URLWithString:@"http://img.ivsky.com/img/tupian/pre/201507/01/yindian_meinv-001.jpg"];
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if (error) {
            NSLog(@"%@",error);
            
        } else {
            
            NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            
            NSLog(@"%@ \n%@",response, reuslt);
        }         
    }];
    
    [uploadTask resume];

代理方式

簽定代理協議

@interface ViewController ()<NSURLSessionDataDelegate>
NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];
    request.HTTPMethod = @"POST";

設置請求頭,和響應內容

// 設置請求頭的上傳文件的內容格式(Content-Type) 爲圖片類型(image/jpeg)、()
    [request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];
    
    // 設置請求頭的響應(Accept)的文本格式(text/html)
    [request setValue:@"text/html" forHTTPHeaderField:@"Accept"];

把圖片轉換爲Data格式

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5);

代理方式啓動下載

NSURLSession *session  = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData];
    
    
    [uploadTask resume];

代理方法:

上傳完成後調用

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    NSLog(@"%@",response);
}

上傳出錯時調用

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error {
    
    NSLog(@"%@",error);
}

上傳的進度監聽

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
    
    
    NSLog(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
}

##八、後臺下載數據

讓程序在後臺狀態本身下載任務,下載完成後屏幕上方顯示一個提示

簽定代理協議

@interface ViewController ()<NSURLSessionDownloadDelegate>

建立URL和請求

NSURL *url = [NSURL URLWithString:@"https://github.com/fuqinglin/MagicalRecord/archive/master.zip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];

設置網絡請求爲 backgroundSessionConfigurationWithIdentifier 後臺模式,後面接標識符

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.tens.background"];

建立NSURLSession,啓動下載任務

NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
    
    [downloadTask resume];

代理方法: 下載完成

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    
    NSLog(@"下載完成");
}

下載進度

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    
    
    NSLog(@"%lld %lld %lld",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}

後臺下載完調用

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    
    NSLog(@"後臺下載完成");
    
    AppDelegate *delegate = [UIApplication sharedApplication].delegate;
    
    // 回調 AppDelegate 中 application: handleEventsForBackgroundURLSession: completionHandler: 中的block事件,處理下載完後的提示
    if (delegate.backgroundCompletionHandler) {
        
        void (^completionHandler)() = delegate.backgroundCompletionHandler;
        
        completionHandler();
    
    }
}

在AppDelegate.m中註冊發送通知的權限

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 註冊發送通知的權限
    [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]];
    
   
    return YES;
}

監聽後臺下載任務完成

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
    
    NSLog(@"------後臺下載完成");

    self.backgroundCompletionHandler = completionHandler;
    
    [self notification];
}

發送本地通知

- (void)notification{
    
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.fireDate = [[NSDate date] dateByAddingTimeInterval:2];
    notification.alertTitle = @"下載任務提示";
    notification.alertBody = @"下載完成";
    notification.soundName = UILocalNotificationDefaultSoundName;
    notification.applicationIconBadgeNumber = 1;
    
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

##九、第三方框架AFNetWorking使用更方便,功能更多,便捷

下載地址:AFNetWorking

Demo下載地址:

https://github.com/fuxinto/HfxDemo

相關文章
相關標籤/搜索