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

相关文章
相关标签/搜索