介绍iOS中的两种网络编程。
iOS原生网络编程:支持后台下载上传、提供全局session、下载时是多线程异步处理效率更高。
使用上非常简单、创建一个请求Task然后执行。NSURLSessionTask有一些子类:NSURLSessionDataTask(发送常见的Get,Post请求)、NSURLSessionDownloadTask(发送下载请求)、NSURLSessionUploadTask(发送上传请求)
1. NSURLSession发送Get请求
//创建请求路径
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://39.98.152.99:80/login?username=%@&password=%@",username,password]];
//创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//获得会话对象
NSURLSession *session = [NSURLSession sharedSession];
//创建Task并执行,在block里接收返回数据
NSURLSessionTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(error == nil) {
//接收字符串数据
NSString *responseInfo = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//接收字典类型
NSDictionary *responseInfo = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}else{
NSLog(@"error:%@",error);
}
}];
[dataTask resume];
2. NSURLSession发送Post请求
//确定请求路径
NSURL *url = [NSURL URLWithString:@"http://39.98.152.99:80/login"];
//创建可变请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求方法与请求体
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=jack&password=123" dataUsingEncoding:NSUTF8StringEncoding];
//创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//创建Task并执行
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
3. 使用代理完成请求
监听网络请求的过程,需要遵守协议并实现代理方法。
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://39.98.152.99:80/login?username=%@&password=%@",username,password]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSOperationQueue alloc] init]
则在子线程中调用,示例为主线程。NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
@interface LoginViewController ()<NSURLSessionDataDelegate>
@property (nonatomic, strong) NSMutableData *mData;
@end
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
//收到服务器响应的时候调用
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//打印http信息
NSHTTPURLResponse *htttpResponse = (NSHTTPURLResponse *)response;
NSLog(@"响应头:%@",htttpResponse.allHeaderFields);
//定义一个容器用于接受服务器返回的数据
self.mData = [NSMutableData data];
//收到响应信息之后,需要使用completionHandler回调告诉系统应该如何处理服务器返回的数据
//默认是取消的(NSURLSessionResponseCancel),继续传递数据(NSURLSessionResponseAllow)
completionHandler(NSURLSessionResponseAllow);
}
//收到服务器返回数据的时候会调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
[_mData appendData:data];
}
//请求完成(成功|失败)的时候会调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//解析服务器返回的数据
}
第三方框架,由NSURLSession(AFURLSessionManager、AFHTTPSeesionManager)、Serialization( 协议、 协议)、AFSecurityPolicy(安全)、其他缓存。
1. AFURLSessionManager(和NSURLSession很相似)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];
[dataTask resume];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
//创建请求对象
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
//创建任务
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
}completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
NSLog(@"File downloaded to: %@", filePath);
}];
//启动任务
[downloadTask resume];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Success: %@ %@", response, responseObject);
}
}];
[uploadTask resume];
2. AFHTTPSeesionManager、是封装的子类,更便捷(推荐)。
//1.创建AFHTTPSessionManager管理者(内部是基于NSURLSession实现)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.发送请求
NSDictionary *param = @{@"username":@"520it",@"pwd":@"520it"};
[manager GET:@"http://120.25.226.186:32812/login" parameters:param success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
NSLog(@"请求成功 %@",[responseObject class]);
}failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
NSLog(@"失败 %@",error);
}];
//responseObject是请求成功返回的响应结果、通常是字典或数组
-(void)download
{
//创建一个管理者
AFHTTPSessionManager *manage = [AFHTTPSessionManager manager];
//创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"]];
//创建下载进度并监听
NSProgress *progress = nil;
NSURLSessionDownloadTask *downloadTask = [manage downloadTaskWithRequest:request progress:&progress destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//拼接文件全路径
NSString *fullpath = [caches stringByAppendingPathComponent:response.suggestedFilename];
NSURL *filePathUrl = [NSURL fileURLWithPath:fullpath];
return filePathUrl;
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nonnull filePath, NSError * _Nonnull error) {
NSLog(@"文件下载完毕---%@",filePath);
}];
//参数:请求对象、下载进度、block回调,返回下载文件的目标地址、下载完成之后调用的block
//使用KVO监听下载进度
[progress addObserver:self forKeyPath:@"completedUnitCount" options:NSKeyValueObservingOptionNew context:nil];
[downloadTask resume];
}
//获取并计算当前文件的下载进度
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(NSProgress *)progress change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"%zd--%zd--%f",progress.completedUnitCount,progress.totalUnitCount,1.0 * progress.completedUnitCount/progress.totalUnitCount);
}
-(void)upload
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//发送POST请求上传数据
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//把本地的图片转换为NSData类型的数据
UIImage *image = [UIImage imageNamed:@"123"];
NSData *data = UIImagePNGRepresentation(image);
[formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
NSLog(@"请求成功---%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
NSLog(@"请求失败--%@",error);
}];
}
另一种上传请求根据url确定文件
-(void)upload2
{
//1.创建一个请求管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSDictionary *dict = @{
@"username":@"wenidngding"
};
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//本地文件的url
NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文顶顶/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];
[formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
NSLog(@"请求成功---%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
NSLog(@"请求失败--%@",error);
}];
}