iOS学习之路06

来源:互联网 发布:淘宝模块怎么添加名称 编辑:程序博客网 时间:2024/05/17 01:56
  • 官方网络框架 NSURLConnection
    • 重要概念
      • ShowAPI:web server提供网站
      • NSURLSessionTask类结构

    • NSURLSessionDataTask
      • get方式
        • 创建NSURLRequest(URL请求)对象

          NSURL *url = [NSURL URLWithString:strUrl];

          NSURLRequest *request = [NSURLRequest requestWithURL:url];

        • 获取单例NSURLSession(URL会话)对象

          必须使用单例,因为单例已经配置好NSURLSession对象。设置好了其他未设置好的参数

          NSURLSession *session = [NSURLSession sharedSession];

        • 创建NSURLSessionDataTask(URLSession会话任务)对象,负责执行会话任务 completionHandler:回调block

          NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

          if (!error) {

          id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

          NSLog(@"%@",jsonData);

          } else {

          NSLog(@"请求错误:%@",error);

          }

          }];

        • 会话任务 重新开始

          [sessionDataTask resume];

      • post方式
        • 创建NSMutableURLRequest(可变URL请求)对象,需要设置参数

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

          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        • 设置请求模式为post

          request.HTTPMethod = @"post";

        • 设置请求体,POST请求的参数数据要使用HTTPBody(请求体)的方式发送,需设置请求方式(HTTPMethod)为POST.

          NSString *appid = @"16469";

          NSString *timestamp = [NSDate formatDateStringForCurrDate];

          NSString *topid = @"5";

          NSString *sign = @"8f39335f503741ed96744cda3c0a7b52";

          NSString *strHttpBody = [NSString stringWithFormat:@"showapi_appid=%@&showapi_timestamp=%@&topid=%@&showapi_sign=%@",appid,timestamp,topid,sign];

          NSData *data_httpBody = [strHttpBody dataUsingEncoding:NSUTF8StringEncoding];

          request.HTTPBody = data_httpBody;

        • 获取单例NSURLSession(URL会话)对象

          NSURLSession *session = [NSURLSession sharedSession];

        • 创建 NSURLSessionTask(URL会话任务)对象,负责执行会话任务 completionHandler:回调block

          NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

          if (!error) {

          id jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

          NSLog(@"%@",jsonData);

          } else {

          NSLog(@"请求错误:%@",error);

          }

          }];

        • 会话任务 重新开始

          [dataTask resume];

      • NSURLSessionConfiguration(URL会话配置)
        • 创建请求模式

          /* 创建请求模式

          1、defaultSessionConfiguration 默认模式,会有缓存、cookie

          2、ephemeralSessionConfiguration 不会缓存,无痕浏览

          3、backgroundSessionConfigurationWithIdentifier 后台任务模式

          */

          NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];

        • 设置缓存机制,属性requestCachePolicy

          NSURLRequestUseProtocolCachePolicy = 0, 默认机制,有缓存先加载缓存,没有进行网络获取。但是会判断缓存的有效性,缓存过期不会加载。

          NSURLRequestReloadIgnoringLocalCacheData = 1, 不加载缓存,总是请求网络

          NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,

          NSURLRequestReturnCacheDataElseLoad = 2, 有缓存先加载缓存,没有进行网络获取。不会判断缓存的有效性

          NSURLRequestReturnCacheDataDontLoad = 3, 只使用缓存,没有也不进行网络请求

    • NSURLSessionDownloadTask 下载任务
      • 使用方式

        NSString *strUrl = @"http://tsmusic24.tc.qq.com/105593336.mp3";

        NSURL *url = [NSURL URLWithString:strUrl];

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

        NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];

        [downloadTask resume];

      • NSURLSessionDownloadDelegate委托
        • 下载会话,每次从服务器获取到数据时触发

          - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

        • 下载完成后触发

          - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

    • NSURLSessionUploadTask 上传任务
      • 基本使用
        • 创建上传路径URL

          NSURL *uploadUrl = [NSURL URLWithString:@"http://www.mftp.info"];

        • 创建可变URL请求,并设置请求模式为POST

          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:uploadUrl cachePolicy:0 timeoutInterval:20];

          request.HTTPMethod = @"post";

        • 创建会话(URLSession),并设置处理会话的委托。

          NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

        • 创建上传的文件本地URL

          NSURL *fileUrl = [NSURL fileURLWithPath:@"文件路径"];

        • 创建上传任务(URLSessionUploadTask) 设置请求、要上传的文件本地URL

          NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileUrl];

        • 上传任务开始

          [uploadTask resume];

      • NSURLSessionDataDelegate委托
        • 每当上传数据时调用

          - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend

        • 上传完成时调用

          - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data

    • 后台下载
      • 设置NSURLSessionConfiguration对象为后台下载模式

        NSURLSessionConfiguration *config= [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.pengjing.background"];

        • 在backgroundSessionConfiguration:方法中的identifier参数指定了会话的ID,用于标记后台的session。
      • 在AppDelegate类中要实现的方法

        - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler

        • 在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的之后"汇报"下载工作,对每一个后台下载的Task调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:
        • 在方法中需要将completionHandler Block作为属性公开,在后面的Session的委托方法中didFinish时候调用一下
      • 实现NSURLSessionDownloadDelegate委托方法

        - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session

        • (程序进入后台,但UIApplication却任然在监听)UIApplication监听到downloadTask(下载任务)完成后,会先调用UIApplication的代理方法handleEventsForBackgroundURLSession,然后汇报下载工作,最后每个后台下载完成了的任务都会调用URLSessionDidFinishEventsForBackgroundURLSession委托方法
        • 在这个方法中需要调用存放completionHandler的属性,并执行一下,否则会报错
      • 如果是一个BackgroundSession,在Task执行的时候,用户切到后台,Session会和ApplicationDelegate做交互。当程序切到后台后,在BackgroundSession中的Task还会继续下载,这部分文档叙述比较少,现在分三个场景分析下Session和Application的关系:
        • 当加入了多个Task,程序没有切换到后台。

          这种情况Task会按照NSURLSessionConfiguration的设置正常下载,不会和ApplicationDelegate有交互。

        • 当加入了多个Task,程序切到后台,所有Task都完成下载。

          在切到后台之后,Session的Delegate不会再收到,Task相关的消息,直到所有Task全都完成后,系统会调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调,之后"汇报"下载工作,对于每一个后台下载的Task调用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)。之后调用Session的Delegate回调URLSessionDidFinishEventsForBackgroundURLSession:。

        • 当加入了多个Task,程序切到后台,下载完成了几个Task,然后用户又切换到前台。(程序没有退出)

          切到后台之后,Session的Delegate仍然收不到消息。在下载完成几个Task之后再切换到前台,系统会先汇报已经下载完成的Task的情况,然后继续下载没有下载完成的Task,后面的过程同第一种情况。

        • 当加入了多个Task,程序切到后台,几个Task已经完成,但还有Task还没有下载完的时候关掉强制退出程序,然后再进入程序的时候。(程序退出了)

          最后这个情况比较有意思,由于程序已经退出了,后面没有下完Session就不在了后面的Task肯定是失败了。但是已经下载成功的那些Task,新启动的程序也没有听"汇报"的机会了。经过实验发现,这个时候之前在NSURLSessionConfiguration设置的NSString类型的ID起作用了,当ID相同的时候,一旦生成Session对象并设置Delegate,马上可以收到上一次关闭程序之前没有汇报工作的Task的结束情况(成功或者失败)。但是当ID不相同,这些情况就收不到了,因此为了不让自己的消息被别的应用程序收到,或者收到别的应用程序的消息,起见ID还是和程序的Bundle名称绑定上比较好,至少保证唯一性。

      • UILocalNotification本地推送
        • 当下载任务、上传任务完成后可以发送一条本地推送,告知用户任务已完成
        • 创建方式

          UILocalNotification *localNotification = [[UILocalNotification alloc] init];

        • 常用属性
          • fireDate:开始时间

            例如:localNotification.fireDate = [[NSDate date] dateByAddingTimeInterval:3];

          • timeZone:时区
          • soundName:推送的声音

            例如:localNotification.soundName = UILocalNotificationDefaultSoundName;

          • alertBody:消息内容
          • applicationIconBadgeNumber:显示在icon上的红色圈中的数字,默认为0
        • 使用
          • 将本地推送添加到UIApplication中

            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

          • 要想实现本地推送,首先要得到用户的授权

            // instanceMethodForSelector 为NSObject的类方法。判断每个类是否定义了 SEL 这个方法,返回IMP(真正的函数指针)

            if ([UIApplication instanceMethodForSelector:@selector(registerUserNotificationSettings:)]) {

            /*

            UIUserNotificationTypeNone = 0 无任何效果

            UIUserNotificationTypeBadge = 1 << 0 在状态栏中显示图标

            UIUserNotificationTypeSound = 1 << 1 弹出消息框时伴随着声音(音效)

            UIUserNotificationTypeAlert = 1 << 2 在悬浮框中弹出消息框

            */

            UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert tegories:nil];

            [[UIApplication sharedApplication] registerUserNotificationSettings:setting];

            //将设置好的本地通知进行注册,即询问用户是否同意

            }

    • 断点续传
      • 创建一个下载任务并开始,创建同上
      • 使用NSURLSessionDownloadTask对象的实例方法

        cancelByProducingResumeData:^(NSData * _Nullable resumeData) 暂停下载任务,并执行block代码块(将resumeData数据保存到本地)

        // cancelByProducingResumeData暂停下载任务,并执行block代码块。

        [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

         

        resumeFileData = resumeData;

         

        // NSUserDefaults写入plist文件

        NSUserDefaults *userInfo = [NSUserDefaults standardUserDefaults];

         

        [userInfo setValue:resumeData forKey:LWResumeData];

         

        float progressValue = (float)self.downloadTask.countOfBytesReceived/self.downloadTask.countOfBytesExpectedToReceive;

         

        self.viewProgress.progress = progressValue;

        [userInfo setValue:@(progressValue) forKey:LWProgressValue];

         

        [userInfo synchronize];

        }];

      • 当要重新开始时,获取本地resumeData数据

        使用NSURLSession的实例方法downloadTaskWithResumeData: 创建下载任务,并让下载任务继续开始

        // 让下载任务从 某个数据端的末尾 重新开始

        self.downloadTask = [self.session downloadTaskWithResumeData:resumeFileData];

        // 下载任务 重新开始

        [self.downloadTask resume];

  • 第三方网络框架 AFNetWorking
    • 重点知识点
      • CocoaPods导入AFNetworking命令

        pod 'AFNetworking','~>3.0'

      • 常用到的类

        AFHTTPSessionManager:GET、POST请求

        AFURLSessionManager:dataTask、uploadTask、downloadTask

      • 请求格式类

        AFHTTPRequestSerializer:二进制格式

        AFJSONRequestSerializer:JSON

        AFPropertyListRequestSerializer:PList(是一种特殊的XML,解析起来相对容易)

      • 返回格式类

        AFHTTPResponseSerializer:二进制格式

        AFJSONResponseSerializer:JSON

        AFXMLParserResponseSerializer:XML,只能返回XMLParser,还需要自己通过代理方法解析

        AFXMLDocumentResponseSerializer:(Mac OS X)

        AFPropertyListResponseSerializer:PList

        AFImageResponseSerializer:Image

        AFCompoundResponseSerializer:组合

        注意:默认提交的请求数据是二进制,返回的则是JSON。如果提交的数据是JSON,需将请求格式设置为AFJSONRequestSerializer。如果返回的数据是二进制,需将返回格式设置为AFHTTPResponseSerializer

    • 使用AFHTTPSessionManager类发送POST请求

      AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      manager.responseSerializer = [AFHTTPResponseSerializer serializer];

       

      NSString *postUrlStr = @"http://www.mftp.info";

      NSURLSessionDataTask *dataTask = [manager POST:postUrlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {

      NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/tens03/Desktop/0.jpg"];

      [formData appendPartWithFileURL:fileUrl name:@"image" fileName:@"0.jpg" mimeType:@"image/jpeg" error:nil];

      } progress:^(NSProgress * _Nonnull uploadProgress) {

      NSLog(@"%lld, %lld",uploadProgress.totalUnitCount,uploadProgress.completedUnitCount);

      } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

      NSLog(@"上传成功:%@",[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);

      } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

      NSLog(@"上传失败");

      }];

      [dataTask resume];

    • 使用AFHTTPSessionManager类上传文件

      // 1、创建可变URL请求(因为是上传任务,所以必须设置为POST方式)

      // 第一种 通过AFJSONRequestSerializer创建 当需要传递参数时使用

      AFHTTPRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];

      NSString *strUrl = @"http://www.mftp.info";

      NSMutableURLRequest *request = [requestSerializer requestWithMethod:@"POST" URLString:strUrl parameters:nil error:nil];

      /* 第二种 通过NSMutableURLRequest创建 当不需要传递参数时使用

      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.mftp.info"]];

      request.HTTPMethod = @"POST";

      */

       

      // 2、创建AFURLSessionManager(Session管理)对象 相当于NSURLSession对象

      AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

      // 设置服务器响应数据序列化的代理对象,默认是AFJsonResponseSerializer对象

      manager.responseSerializer = [AFHTTPResponseSerializer serializer];// 通过类方法serializer创建,会对属性进行默认设置

       

      NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/tens03/Desktop/0.jpg"];

      // 3、创建NSURLSessionUploadTask(上传任务)对象,通过AFURLSessionManager对象的uploadTaskWithRequest实例方法

      NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:fileUrl progress:nil completionHandler:^(NSURLResponse * _Nonnull sponse, id _Nullable responseObject, NSError * _Nullable error) {

      if (!error) {

      NSLog(@"success: %@",response);

      } else {

      NSLog(@"error: %@",error);

      }

      }];

      // 4、上传任务 重新开始

      [uploadTask resume];

原创粉丝点击