天天看点

iOS进阶_NSURLRequest(二.参数整理&JSON解析&Plist文件反序列化)

详细分析iOS网络请求方式

第一种方式:NSData 方法 在实际开发中用不到

因为:

- 默认超时时长 60s,没有办法修改,且没有缓存策略

- dataWithContentsOfURL 是同步方法

- 没有错误处理机制

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSData * data =[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://127.0.0.1/demo.json"]];
    NSString * json = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",json);
}
@end
           

第二种方式:NSURLRequest 方法

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

参数:

  • timeoutInterval:超时时长

    一般在实际开发中建议:15到30秒,太短了可能服务器来不及做出响应,太长了用户等待太久,影响用户体验

    -SDWebImage 默认时长 15s

    -AFNetworking 默认时长 60s

  • cachePolicy:缓存策略

NSURLRequestUseProtocolCachePolicy = 0, 默认缓存策略

NSURLRequestReload(刷新)Ignoring(忽略)Local(本地)Cache(缓存)Data = 1, 忽略本地缓存数据,直接加载网络数据,每次都是“最新数据”

应用场景:数据变化非常频繁的App 股票,彩票

提示:以下两个选项,专门用于离线浏览的,建议结合 Reachalibity 框架联合使用
      - 如果用户当前没有网络,就使用默认缓存策略
      - 如果有网络就用默认缓存策略
           

NSURLRequestReturnCacheDataElseLoad = 2, 返回缓存数据,如果没有缓存从服务器加载

NSURLRequestReturnCacheDataDontLoad = 3, 返回缓存数据,如果没有缓存就空着

NSURLConnection sendAsynchronousRequest

  • 1.request - 索要资源的请求
  • 2.queue - 调度任务的队列
    指定调度回调代码块的队列
    - 主队列,回调的代码块在主线程上执行
    - 新建队列,就会在其他线程执行回调代码
    如何选择?是否需要更新UI
               
  • 3.block - 回调代码块,网络请求结束后执行
    3.1 response(NSHTTPURLResponse):服务器响应
        URL      服务器返回的URL,绝大部分和请求的URL是一样的,“请求重定向”的时候不一样
        MIMEType 二进制数据的文件类型,服务器会告诉客户端,可以使用什么软件打开二进制数据
        expectedContentLength  下载文件的长度
        textEncodingName       文本编码名称,大多是UTF8
        suggestedFilename      服务器建议保存的文件名称
        statusCode             状态码 2XX 3XX(重定向) 4XX(客户端问题) 5XX服务器问题
        allHeaderFields        所有响应头的内容
    
    3.2 data:数据实体,程序员开发最关注的
    3.3 connectionError:错误处理
        注意:实际开发中有一种情况是没有错误,也没有数据
         if(connectionError || data == nil){
            NSLog("您的网络不给力,请稍后再试!");
         }
               
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];  
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1/demo.json"];

    NSURLRequest * request =[NSURLRequest requestWithURL:url cachePolicy: timeoutInterval:];
    //异步发送,错误处理机制
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        NSLog(@"%@",response);

        NSString * json = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@",json);
    }];
    NSLog(@"come here");
}

@end
           

JSON详解

JSON目前最流行的网络传输数据格式,没有之一

JSON语法是JavaScript对象标示语法的子集

OC中字典的快速包装方法,就是借鉴了JSON的格式

JSON 本质上就是一个特殊格式的字符串,出自于民间被广泛的使用

JSON的解析并不是表面上的那么简单,出现过的JSON解析的三方框架 JSONKit(iOS5.0停止更新) SBJson TouchJSON

id result = [NSJSONSerialization JSONObjectWithData:data options: error:NULL];
           

NSJSONSerialization JSONObjectWithData 能够将网络返回的二进制数据转换成为字典或者数组

  • 官方说明:

    A class for converting JSON to Foundation objects and converting

    Foundation objects to JSON.

    An object that may be converted to JSON must have the following properties:
          一个Json对象应该具有以下属性
        - Top level object is an NSArray or NSDictionary
          顶级节点是一种数组或者字典
        - All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
          所有对象必须是NSString, NSNumber, NSArray, NSDictionary, or NSNull
        - All dictionary keys are NSStrings
          所有的字典的KEY 必须是 NSStrings
        - NSNumbers are not NaN or infinity
          NSNumbers 不能是无理数或者空
               

参数options是一个枚举类型

  • MARK:关于枚举

    C语言定义枚举的类型,枚举的数据类型是不确定的,会默认的使用int

    iOS6.0之后推出两个宏 NS_ENUM & NS_OPTIONS

    NS_ENUM:定义枚举的同时,指定数据的类型

    NS_OPTIONS:定义的枚举是位移的,可以用按位或 来设置数值

    如果看到NS_OPTIONS 定义的枚举,直接传入0 作为参数,表示什么附加操作也不做,效率最高

    options:

    typedef NS_OPTIONS(NSUInteger, NSJSONReadingOptions) {

    NSJSONReadingMutableContainers = (1UL << 0), 容器节点是可变的

    NSJSONReadingMutableLeaves = (1UL << 1), 子节点是可变的

    NSJSONReadingAllowFragments = (1UL << 2) 允许顶级节点不是 NSArray 或者 NSDictionary

    } API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));

    按位或示例:

    id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:NULL];

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1/demo.json"];
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
       //解析数据
       //二进制数据 -> OC对象:反序列化
//        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

        id result = [NSJSONSerialization JSONObjectWithData:data options: error:NULL];

        NSLog(@"%@  %@",result,[result class]);
        for (NSDictionary * dict in result) {
            NSLog(@"==> %@",dict);
        }
    }];
}

@end
           

Plist文件反序列化

- (void)viewDidLoad {
    [super viewDidLoad];
    //plist 很少用于传输网络数据,只是苹果使用的比较多
    NSURL * url = [NSURL URLWithString:@"http://127.0.0.1/messages.plist"];

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

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //NSJson(JSON) NSJSONSerialization(序列化)
        //NSProperty(属性)Serialization(序列化)
        /*
         options枚举类型:
         typedef NS_OPTIONS(NSUInteger, NSPropertyListMutabilityOptions) {
         NSPropertyListImmutable = kCFPropertyListImmutable,
         不可变
         NSPropertyListMutableContainers = kCFPropertyListMutableContainers,
         容器可变
         NSPropertyListMutableContainersAndLeaves = kCFPropertyListMutableContainersAndLeaves
         容器和子节点可变的
         };
         */
       id result = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:NULL];
        NSLog(@"%@  %@",result,[result class]);
    }];
}