网络

NSURLConnection

NSURLSession

普通网络请求

JSON数据解析

JSON序列化

数据解析

解析规则:

具体示例

重写setValue: forUndefinedKey:方法

重写setNilValueForKey:方法

解析的几种方式

KVC

网络类的基本封装(非终极版)

SDWebImage

MJRefresh

NSURLConnection

这种网络请求方式, 在iOS9已经被彻底抛弃了. 官方推荐使用功能更加强大完善的NSURLSession.

NSURLSession

iOS7之后生效的原生网络请求类, 取代之前的NSURLSession

普通网络请求

NSURLSession*session = [NSURLSessionsharedSession];

NSURLSessionDataTask*task = [session dataTaskWithURL:[NSURLURLWithString:kHeroPath] completionHandler:^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {

/*data参数就是从网络上下载下来的数据

这个数据是服务器把 字典/数组 根据JSON协议编码以后生成的. 拿到JSON数据以后, 我们要反编码 回到字典或者数组

*/

//因为根据返回值类型, 可以看到是字典类型的

//Serialization:序列化

//参数2:options 代表当前data原始数据是什么类型

//MutableContainers:代表原始数据是数组/字典

NSError*err =nil;

NSDictionary*responseObj = [NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableContainerserror:&err];

NSLog(@"responseObj %@", responseObj);

self.parse= [HerosParse parse:responseObj];

NSLog(@"");

//数据获取完成以后, 要刷新界面. 网络请求是子线程, 刷新界面要回归主线程

[[NSOperationQueuemainQueue] addOperationWithBlock:^{

[_tableView reloadData];//刷新界面

}];

}];

//开始发送请求

[task resume];

JSON数据解析

JSON序列化

数据从服务器传递到终端, 数据通常是字典或者数组类型, 当传递这些类型时,

需要通过一定的规则把数组/字典转化为字符串的形式, 这个规则称为Json.

当终端获取到这些字符串时, 需要再重新转换为数据原本的样式.

我们称这种 字典/数组 和 JSON样式字符串 之间的转化, 为JSON序列化

//把JSON的数据 转换为 原始状态

NSError*err =nil;

NSDictionary*responseObj = [NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableContainerserror:&err];

//参数2 代表原始状态的数据类型

typedefNS_OPTIONS(NSUInteger,NSJSONReadingOptions) {

NSJSONReadingMutableContainers= (1UL <<0),//可变数组/字典

NSJSONReadingMutableLeaves= (1UL <<1),//可变字符串

NSJSONReadingAllowFragments= (1UL <<2)//允许JSON字符串最外层既不是NSArray也不是NSDictionary,但必须是有效的JSON Fragment

}NS_ENUM_AVAILABLE(10_7,5_0);

//把OC类型 转为 JSON数据

[NSJSONSerializationdataWithJSONObject:responseObj options:NSJSONWritingPrettyPrintederror:nil];

数据解析

在使用字典时, 要经常使用字符串的key来获取字典中的value, 这样用起来很麻烦.

因为字符串没有代码提示, 容易犯错. 这时候就自然有了一个需求, 要把字典转化为对象来使用.

我们称这种把字典转化为类的方式为数据解析.

解析规则:

遇到字典则新建类型

建完类型以后 立刻把所有的键对应的属性声明

每个类型都需要一个解析 类方法

对于数组类型的属性, 要标记它的内容, 通过@class引入类型

解析方法的实现顺序, 由底层向表层实现

具体示例

//对于下方字典的解析操作

{

"all": [

{

"cnName":"俄洛伊",

"enName":"Illaoi",

"location":"上单",

"price":"6300,4500",

"rating":"8,6,3,4",

"tags":"fighter",

"title":"海兽祭司"

}]

}

//解析类

@classHerosAllParse;

@interfaceHerosParse:NSObject

@property(nonatomic)NSArray *all;

+ (instancetype)parse:(NSDictionary*)dic;

@end

@interfaceHerosAllParse:NSObject

@property(nonatomic)NSString*cnName;

@property(nonatomic)NSString*enName;

@property(nonatomic)NSString*location;

@property(nonatomic)NSString*price;

@property(nonatomic)NSString*rating;

@property(nonatomic)NSString*tags;

@property(nonatomic)NSString*title;

+ (instancetype)parse:(NSDictionary*)dic;

@end

@implementationHerosParse

+ (instancetype)parse:(NSDictionary*)dic{

NSMutableArray*arr = [NSMutableArraynew];

NSArray*array = dic[@"all"];

for(NSDictionary*dicinarray) {

[arr addObject:[HerosAllParse parse:dic]];

}

//把内容是字典的数组 替换为 内容是**类型的数组

NSMutableDictionary*mutableDic = [NSMutableDictionarydictionaryWithDictionary:dic];

[mutableDic setObject:arr forKey:@"all"];

idobj = [selfnew];

[obj setValuesForKeysWithDictionary:mutableDic];

returnobj;

}

- (void)setValue:(id)value forUndefinedKey:(NSString*)key{}

- (void)setNilValueForKey:(NSString*)key{}

@end

@implementationHerosAllParse

+ (instancetype)parse:(NSDictionary*)dic{

idobj = [selfnew];

[obj setValuesForKeysWithDictionary:dic];

returnobj;

}

- (void)setValue:(id)value forUndefinedKey:(NSString*)key{}

- (void)setNilValueForKey:(NSString*)key{}

@end

重写setValue: forUndefinedKey:方法

通过重写此方法, 可以防止对不存在的key使用KVC方式复制, 而导致的崩溃现象

重写setNilValueForKey:方法

通过重写此方法, 可以防止对key赋nil值, 导致的崩溃现象

解析的几种方式

//通过KVC方式赋值, 可以有效减少代码量

+ (HeroParse *)parse:(NSDictionary *)dic{

HeroParse *parse = [self new];

//自动把字典的键值对应放到属性中

[parsesetValuesForKeysWithDictionary:dic];

//遍历字典enumerate: 遍历,枚举

/*

[dic enumerateKeysAndObjectsUsingBlock:^(id_Nonnull key, id_Nonnull obj, BOOL * _Nonnull stop) {

[parsesetValue:objforKey:key];

}];

*/

//通过KVC的方式对属性进行赋值

//[parsesetValue:dic[@"cnName"]forKey:@"cnName"];

//parse.cnName = dic[@"cnName"];

/*

parse.enName = dic[@"enName"];

parse.location = dic[@"location"];

parse.price = dic[@"price"];

parse.rating = dic[@"rating"];

parse.tags = dic[@"tags"];

parse.title = dic[@"title"];

*/

returnparse;

}

KVC

除了一般的赋值和取值的方法,我们还可以用Key-Value-Coding(KVC)键值编码来访问你要存取的类的属性。

例如:

@interfaceStudent:NSObject

@propertyNSString*name;

@end

Student *stu = [Student new];

//这是使用getter和setter方法来对值进行读取和写入操作

stu.name=@"小明";

NSLog(@"%@", stu.name);

//KVC方式

[stu setValue:@"小明"forKey:@"name"];

NSLog(@"%@", [stu valueForKey:@"name"]);

网络类的基本封装(非终极版)

根据程序的设计原则: MVC, 解耦和

ViewController应该只负责把数据呈现在View上

所以要把网络请求的逻辑独立放在外部

@interfaceServerNetwork:NSObject

+ (id)getServerListCompletionHandle:(void(^)(idmodel,NSError*error))completionHandle;

@end

@implementation

+ (id)getServerListCompletionHandle:(void(^)(id,NSError*))completionHandle{

NSString*path =@"http://lolbox.duowan.com/phone/apiServers.php?v=77&OSType=iOS8.2&versionName=2.1.7";

NSURLSessionDataTask*task = [[NSURLSessionsharedSession] dataTaskWithURL:[NSURLURLWithString:path] completionHandler:^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {

if(error) {//请求操作出现问题

completionHandle(nil, error);

return;

}

NSError*err =nil;

NSArray*arr = [NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableContainerserror:&err];

if(err) {//JSON解析出错了

completionHandle(nil, err);

return;

}

//开始解析

NSMutableArray*mulArr = [NSMutableArraynew];

for(NSDictionary*dicinarr) {

[mulArr addObject:[ServerParse parse:dic]];

}

//为了安全考虑,返回的数组应该是不可变数组

completionHandle([mulArrcopy],nil);

}];

[task resume];

returntask;

}

@end

SDWebImage

github上目前最好的为原生控件增加网络图片功能的第三方类库.SDWebImage

//专门用于为图片控件添加网络操作的Category

#import"UIImageView+WebCache.h"

//SDWebImage

UIImageView*iconIV = [UIImageViewnew];

NSString*path = [NSStringstringWithFormat:@"http://img.lolbox.duowan.com/champions/%@_120x120.jpg", _heroInfo.enName];

//SDWebImage让UIImageView类型拥有了网络功能

[iconIV sd_setImageWithURL:[NSURLURLWithString:path]];

MJRefresh

国人编写的, 为滚动视图添加刷新UI的第三方框架.MJRefresh

官方有详细的中文文档, 自行查看

#import"MJRefresh.h"//上下拉动的UI显示

//为表格添加下拉刷新头部UI控件

_tableView.mj_header= [MJRefreshNormalHeader headerWithRefreshingBlock:^{

[ServerNetwork getServerListCompletionHandle:^(idmodel,NSError*error) {

if(error) {

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

}else{

self.servers= model;

//刷新界面要在主线程中做

[[NSOperationQueuemainQueue] addOperationWithBlock:^{

[_tableView reloadData];

}];

}

[[NSOperationQueuemainQueue] addOperationWithBlock:^{

//结束刷新操作

[_tableView.mj_headerendRefreshing];

}];

}];

}];

//刚运行时,应该刷新一次

[_tableView.mj_headerbeginRefreshing];

你可能感兴趣的:(网络)