网络02

作者: 木子尚武 | 来源:发表于2016-03-27 16:18 被阅读54次

JSON数据解析:

  • JSON的简单介绍:
    • 什么是JSON
    • JSON以一种轻量级的数据格式,一般用来数据交互
    • 服务器返回给客户端的数据一般都是JSON或者XML格式(问价下载除外)
    • JSON相关说明
    • JSON格式很想oc中的字典
    • 标准JSON格式中的key必须是双引号
    • 解析JSON的方案
    • 第三方框架
    • 苹果原生:NSJSONSerialization
  • JSON解析相关代码
    • JSON数据->OC(反序列化)
      //把json数据转换为OC对象
         -(void)jsonToOC
         {
             //1. 确定url路径
             NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=33&pwd=33&type=JSON"];
    
             //2.创建一个请求对象
             NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
             //3.使用NSURLSession发送一个异步请求
             [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
    
                 //4.当接收到服务器响应的数据后,解析数据(JSON--->OC)
    
                 /*
                  第一个参数:要解析的JSON数据,是NSData类型也就是二进制数据
                  第二个参数: 解析JSON的可选配置参数
                  NSJSONReadingMutableContainers 解析出来的字典和数组是可变的
                  NSJSONReadingMutableLeaves 解析出来的对象中的字符串是可变的  iOS7以后有问题
                  NSJSONReadingAllowFragments 被解析的JSON数据如果既不是字典也不是数组, 那么就必须使用这个
                  */
                 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
                 NSLog(@"%@",dict);
    
             }];
         }
    
    • OC对象->JSON对象
      //1.要转换成JSON数据的OC对象*这里是一个字典
            NSDictionary *dictM = @{
                                    @"name":@"wendingding",
                                    @"age":@100,
                                    @"height":@1.72
                                    };
            //2.OC->JSON
            /*
             注意:可以通过+ (BOOL)isValidJSONObject:(id)obj;方法判断当前OC对象能否转换为JSON数据
             具体限制:
                 1.obj 是NSArray 或 NSDictionay 以及他们派生出来的子类
                 2.obj 包含的所有对象是NSString,NSNumber,NSArray,NSDictionary 或NSNull
                 3.字典中所有的key必须是NSString类型的
                 4.NSNumber的对象不能是NaN或无穷大
             */
            /*
             第一个参数:要转换成JSON数据的OC对象,这里为一个字典
             第二个参数:NSJSONWritingPrettyPrinted对转换之后的JSON对象进行排版,无意义
             */
            NSData *data = [NSJSONSerialization dataWithJSONObject:dictM options:NSJSONWritingPrettyPrinted error:nil];
    
            //3.打印查看Data是否有值
            /*
             第一个参数:要转换为STring的二进制数据
             第二个参数:编码方式,通常采用NSUTF8StringEncoding
             */
            NSString *strM = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"%@",strM);
    
  • OC对象与JSON对象之间的一一对应关系
      //OC对象和JSON数据之间的一一对应关系
         -(void)oCWithJSON
         {
             //JSON的各种数据格式
             //NSString *test = @"\"wendingding\"";
             //NSString *test = @"true";
             NSString *test = @"{\"name\":\"wendingding\"}";
    
             //把JSON数据->OC对象,以便查看他们之间的一一对应关系
             //注意点:如何被解析的JSON数据如果既不是字典也不是数组(比如是NSString), 那么就必须使用这NSJSONReadingAllowFragments
             id obj = [NSJSONSerialization JSONObjectWithData:[test dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil];
    
             NSLog(@"%@", [obj class]);
             /* JSON数据格式和OC对象的一一对应关系
                  {} -> 字典
                  [] -> 数组
                  "" -> 字符串
                  10/10.1 -> NSNumber
                  true/false -> NSNumber
                  null -> NSNull
              */
         }
         }
    
  • 如何查看复杂的JSON数据
    ```objc
     [dictM writeToFile:@"/Users/文顶顶/Desktop/videos.plist" atomically:YES];
     ```
    
  • 视频的简单播放
      //0.需要导入系统框架
     #import <MediaPlayer/MediaPlayer.h>
    
     //1.拿到该cell对应的数据字典
     XMGVideo *video = self.videos[indexPath.row];
    
     NSString *videoStr = [@"http://120.25.226.186:32812" stringByAppendingPathComponent:video.url];
    
     //2.创建一个视频播放器
     MPMoviePlayerViewController *vc = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString:videoStr]];
     //3.present播放控制器
    
     [self presentViewController:vc animated:YES completion:nil];
    
  • MJExtension
  • 简单使用
```objc
  //1.把字典数组转换为模型数组
        //使用MJExtension框架进行字典转模型
            self.videos = [XMGVideo mj_objectArrayWithKeyValuesArray:videoArray];

    //2.重命名模型属性的名称
    //第一种重命名属性名称的方法,有一定的代码侵入性
    //设置字典中的id被模型中的ID替换
    +(NSDictionary *)mj_replacedKeyFromPropertyName
    {
        return @{
                 @"ID":@"id"
                 };
    }

    //第二种重命名属性名称的方法,代码侵入性为零
        [XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
            return @{
                     @"ID":@"id"
                     };
        }];

    //3.MJExtension框架内部实现原理-运行时
```

XML解析

  • XML解析
  • 使用XMLParser
  //1.发送请求
 [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

     //2.解析数据
     //2.1 创建XML解析器
     NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];

     //2.2 设置代理
     parser.delegate = self;

     //2.3 开始解析,该方法本身是阻塞的
     [parser parse];

     //4.刷新tableView
     dispatch_async(dispatch_get_main_queue(), ^{
          [self.tableView reloadData];
     });
 }] resume];

 //1.开始解析XML文档
     -(void)parserDidStartDocument:(nonnull NSXMLParser *)parser

     //2.开始解析XML中某个元素的时候调用,比如<video>
     -(void)parser:(nonnull NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary<NSString *,NSString *> *)attributeDict
     {
         if ([elementName isEqualToString:@"videos"]) {
             return;
         }
         //字典转模型
         XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict];
         [self.videos addObject:video];
     }

     //3.当某个元素解析完成之后调用,比如</video>
     -(void)parser:(nonnull NSXMLParser *)parser didEndElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName

     //4.XML文档解析结束
     -(void)parserDidEndDocument:(nonnull NSXMLParser *)parser
  • MJExtension使用小技巧
```objc
//0.告诉框架新值和旧值的对应关系
[XMGVideo mj_setupReplacedKeyFromPropertyName:^NSDictionary *{
    return @{
             @"ID":@"id",
             };

}];
```
  • NSURLSessionDownloadTask大文件下载
  • NSURLSessionDownloadTask实现大文件下载-Block
  • 使用URLSession和URLSessionDownload可以很方便的实现文件下载
  ```objc
    1)使用NSURLSession和NSURLSessionDownload可以很方便的实现文件下载操作
 /*
     第一个参数:要下载文件的url路径
     第二个参数:当接收完服务器返回的数据之后调用该block
     location:下载的文件的保存地址(默认是存储在沙盒中tmp文件夹下面,随时会被删除)
     response:服务器响应信息,响应头
     error:该请求的错误信息
     */
    //说明:downloadTaskWithURL方法已经实现了在下载文件数据的过程中边下载文件数据,边写入到沙盒文件的操作
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * __nullable location, NSURLResponse * __nullable response, NSError * __nullable error)
  ```
-  downloadTaskWithURL内部已经实现了边下载边写入操作,所以开发人员不必担心内存问题
- 文件下载后默认保存到tmp目录,需要手动剪切到指定的沙盒目录
- 缺点:无法监听下载进度
  • 使用NSURLSessionDownloadTask实现大文件下载-代理
  • 创建NSURLSession并设置代理,通过NSURLSessionDownloadTask并以代理的方式实现大文件的下载
      //1.创建NSULRSession,设置代理
      self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
      //2.创建task
      NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
      self.downloadTask = [self.session downloadTaskWithURL:url];
    
      //3.执行task
      [self.downloadTask resume];
    
  • 常用代理方法说明
  ```objc
      /*
     1.当接收到下载数据的时候调用,可以在该方法中监听文件下载的进度
     该方法会被调用多次
     totalBytesWritten:已经写入到文件中的数据大小
     totalBytesExpectedToWrite:目前文件的总大小
     bytesWritten:本次下载的文件数据大小
     */
    -(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    /*
     2.恢复下载的时候调用该方法
     fileOffset:恢复之后,要从文件的什么地方开发下载
     expectedTotalBytes:该文件数据的总大小
     */
    -(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    /*
     3.下载完成之后调用该方法
     */
    -(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location
    /*
     4.请求完成之后调用
     如果请求失败,那么error有值
     */
    -(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
  ```
-  实现断点下载相关代码:
  ```objc
    //如果任务,取消了那么以后就不能恢复了
    //    [self.downloadTask cancel];

    //如果采取这种方式来取消任务,那么该方法会通过resumeData保存当前文件的下载信息
    //只要有了这份信息,以后就可以通过这些信息来恢复下载
    [self.downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
        self.resumeData = resumeData;
    }];

    -----------
    //继续下载
    //首先通过之前保存的resumeData信息,创建一个下载任务
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];

     [self.downloadTask resume];
  ```
-  计算当前下载进度
  ```objc
     //获取文件下载进度
    self.progress.progress = 1.0 * totalBytesWritten/totalBytesExpectedToWrite;
  ```
-  局限性:
  ```objc
    01 如果用户点击暂停之后退出程序,那么需要把恢复下载的数据写一份到沙盒,代码复杂度更
    02 如果用户在下载中途未保存恢复下载数据即退出程序,则不具备可操作性
  ```
  • NSURLSessionDataTask实现大文件下载:
    • 关于NSOutputStream的使用
      //1. 创建一个输入流,数据追加到文件的屁股上
     //把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建
    NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];
    
      //2. 打开流
    [stream open];
    
      //3. 写入流数据
    [stream write:data.bytes maxLength:data.length];
    
     //4.当不需要的时候应该关闭流
    [stream close];
    
    • 关于网络请求头的设置(可以设置指定下载某一部分文件)
      //1. 设置请求对象
      //1.1 创建请求路径
      NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
    
       //1.2 创建可变请求对象
      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
       //1.3 拿到当前文件的残留数据大小
      self.currentContentLength = [self FileSize];
    
       //1.4 告诉服务器从哪个地方开始下载文件数据
       NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];
      NSLog(@"%@",range);
    
      //1.5 设置请求头
      [request setValue:range forHTTPHeaderField:@"Range"];
    
    • NSURLSession对象的释放
            -(void)dealloc
          {
             //在最后的时候应该把session释放,以免造成内存泄露
            //    NSURLSession设置过代理后,需要在最后(比如控制器销毁的时候)调用session的invalidateAndCancel或者resetWithCompletionHandler,才不会有内存泄露
            //    [self.session invalidateAndCancel];
           [self.session resetWithCompletionHandler:^{
      
            NSLog(@"释放---");
           }];
          }
      

文件的压缩与解压缩

  • 说明:
  • 使用ZipArchive来压缩和解压缩文件需要添加依赖库(libz),使用需要包含SSZipArchive文件,如果使用cocoaPoads来安装框架,那么会自动的配置框架的使用环境
  • 相关代码实现:
      //压缩文件的第一种方式
         /*
          第一个参数:压缩文件要保存的位置
          第二个参数:要压缩哪几个文件
          */
         [SSZipArchive createZipFileAtPath:fullpath withFilesAtPaths:arrayM];
    
         //压缩文件的第二种方式
         /*
          第一个参数:文件压缩到哪个地方
          第二个参数:要压缩文件的全路径
          */
         [SSZipArchive createZipFileAtPath:fullpath withContentsOfDirectory:zipFile];
    
         //如何对压缩文件进行解压
         /*
          第一个参数:要解压的文件
          第二个参数:要解压到什么地方
          */
         [SSZipArchive unzipFileAtPath:unZipFile toDestination:fullpath];
    

多值参数和中文输出

  • 多值参数
       /*
      如果一个参数对应着多个值,那么直接按照"参数=值&参数=值"的方式拼接
      */
     -(void)test
     {
         //1.确定URL
         NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/weather?place=Beijing&place=Guangzhou"];
         //2.创建请求对象
         NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
         //3.发送请求
         [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
    
             //4.解析
             NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
         }];
     }
    
    
  • 如何解决字典或者数组输出乱码的问题
  给字典和数组添加一个分类,重写descriptionWithLocale方法,在该方法中拼接元素格式化输出。
  -(nonnull NSString *)descriptionWithLocale:(nullable id)locale

相关文章

网友评论

      本文标题:网络02

      本文链接:https://www.haomeiwen.com/subject/vzfjlttx.html