摘要:
相信大家就算没有使用过YTKNetwork,也应该听过这个框架的大名。如果要看基本功能使用,请参照官方demo。
我会介绍一些基本项目使用实际场景,及上传功能,及遇到的坑.
我来谈谈我是如何使用YTKNetwork的。
首先我会去定义一个基类。
下面是类的.h头文件
只定义了一个initWithDict目的是为了拼接参数
如果你们copy过去用,需要把一些参数改成你们自己公司的.
说到网络请求, 最初我也是使用的自己封装的AFN
但是,思考来去还是觉得离散式网络请求,比较适合我这个项目.
一个网络请求,一个类.意味着我可以对每个网络请求都单独的处理逻辑,以及自定义缓存.
对于说好坏,如果没有使用过,是没有发言权的.既然github上Star有这么多.肯定是有它的道理的.那么我就来使用一番,把它融入到自己项目中.回头再来评论好与坏.
还有关于自定义 acceptableContentTypes
当然在YTKNework的Issues 里面唐巧也回复了,需要KVC强行赋值,这个属性没有开放出来.
YTKNetworkAgent *agent = [YTKNetworkAgent sharedAgent]; [agent setValue:[NSSet setWithObjects:@"application/json", @"text/plain", @"text/javascript", @"text/json",@"text/html",@"text/css", nil] forKeyPath:@"_manager.responseSerializer.acceptableContentTypes"];
// // MTRequest.h // LoveGuQin // // Created by fox on 2018/5/30. // Copyright © 2018年 Moemoe. All rights reserved. // #import "YTKRequest.h" #import <YTKNetwork.h> @interface MTRequest : YTKRequest - (instancetype)initWithDict:(NSDictionary *)dict; @end
这个是.m文件
重写baseurl
如果有多域名的情况下,则可以重写baseurl方法即可
requestArgument
重写这个方法,可以添加一些公共参数
如果要添加请求头
requestHeaderFieldValueDictionary
// // MTRequest.m // LoveGuQin // // Created by fox on 2018/5/30. // Copyright © 2018年 Moemoe. All rights reserved. // #import "MTRequest.h" #import "MTUserModel.h" @interface MTRequest()<YTKRequestAccessory> @end @implementation MTRequest { NSDictionary *_dict; } - (instancetype)initWithDict:(NSDictionary *)dict { if (self = [super init]) { _dict = dict; } return self; } - (NSString *)baseUrl { return @"http://test.moemoetech.com"; } /** 重写请求参数 @return 请求参数 */ -(id)requestArgument { //可以在这里检查参数是否有带Token //如果没有这里可以补一个token // MTLog(@"%@",_dict); return _dict; } /** 按照需重写 默认就post @return post */ - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } /** 如果要添加请求头,可以实现这个方法 @return nullable = 表示可以为null */ - (nullable NSDictionary<NSString *, NSString *> *)requestHeaderFieldValueDictionary { if ([MTUserModel shareUserModel].token.length > 0 ) { NSString *token = [NSString stringWithFormat:@"Bearer %@",[MTUserModel shareUserModel].token]; return @{@"Authorization":token}; }else { return nil; } } @end
如何使用呢?,去看官方文档吧,看这里也行.
这个是我加载数据的方法,只要一进来控制器,数据就会华丽丽的出来了,注意MTMainPersonalRequest 是继承自MTRequest的 - (void)moeupData { MTMainPersonalRequest *request = [[MTMainPersonalRequest alloc]init]; request.delegate = self; [request start]; } /// 请求完成 - (void)requestFinished:(__kindof YTKBaseRequest *)request { MTMainPersonalModel *model = [MTMainPersonalModel yy_modelWithDictionary:request.responseJSONObject]; if ([model.code integerValue] == 1) { _model = model; MTLog(@"%@",_model.data.avatar); [self.tableView reloadData]; }else { [MBProgressHUD MT_ShowError:model.message]; } } /// 失败的回调 - (void)requestFailed:(__kindof YTKBaseRequest *)request { NSString *error = request.error.localizedDescription; [MBProgressHUD MT_ShowError:error]; }
接下里是YTKNetwork的上传功能
这里演示一个上传图片
这个是.h
// // MTPersonalEditRequest.h // LoveGuQin // // Created by fox on 14/06/2018. // Copyright © 2018 Moemoe. All rights reserved. // #import "MTRequest.h" @interface MTPersonalEditRequest : YTKRequest - (instancetype)initImage:(UIImage *)image; @end
这个是.m
// // MTPersonalEditRequest.m // LoveGuQin // // Created by fox on 14/06/2018. // Copyright © 2018 Moemoe. All rights reserved. // #import "MTPersonalEditRequest.h" #import "AFNetWorking.h" #import "MTUserModel.h" @implementation MTPersonalEditRequest { UIImage *_image; } - (NSString *)requestUrl { return @"/api/uploadAva"; } - (instancetype)initImage:(UIImage *)image { if (self = [super init]) { _image = image; } return self; } - (NSString *)baseUrl { return @"http://test.moemoetech.com"; } - (BOOL)statusCodeValidator { return YES; } /** 如果要添加请求头,可以实现这个方法 @return nullable = 表示可以为null */ - (nullable NSDictionary<NSString *, NSString *> *)requestHeaderFieldValueDictionary { if ([MTUserModel shareUserModel].token.length > 0 ) { NSString *token = [NSString stringWithFormat:@"Bearer %@",[MTUserModel shareUserModel].token]; return @{@"Authorization":token}; }else { return nil; } } ///上传必须得显示这个block - (AFConstructingBlock)constructingBodyBlock { return ^(id<AFMultipartFormData> formData) { ///第一步:把图片转换成为禁止 NSData *data = UIImageJPEGRepresentation(_image, 0.9); //拼接时间戳的目的就是为了文件名不重复 NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0]; NSTimeInterval a=[date timeIntervalSince1970]; // *1000 是精确到毫秒,不乘就是精确到秒 NSString *timeString = [NSString stringWithFormat:@"%.0f", a]; //转为字符型 //这个是图片的名字 NSString *name = [NSString stringWithFormat:@"%@.png",timeString]; //formKey 这个字段老重要了,这个字段是后台给的.问后台要,如果字段错了,请求会报错. NSString *formKey = @"file"; // 这里是告诉后台,你传递的图片有哪几种类型 NSString *type = @"png/jpeg/jpg"; [formData appendPartWithFileData:data name:formKey fileName:name mimeType:type]; }; } - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } @end
回到控制器看看是如何使用的
#pragma mark - 点击了保存按钮 - (void)save { [self hudActionWithUploadingWithString:@"上 传 中"]; MTPersonalEditRequest *request = [[MTPersonalEditRequest alloc]initImage:self.image]; request.delegate = self; [request start]; } - (void)requestFinished:(__kindof YTKBaseRequest *)request { NSDictionary *dict = request.responseJSONObject; MTLog(@"%@",request.responseJSONObject); if ([dict[@"code"]integerValue] == 1) { _model.data.avatar = dict[@"data"]; NSDictionary *userDict = [self dicFromObject:_model.data]; MTPersonalEditUploadRequest *request = [[MTPersonalEditUploadRequest alloc]initWithDict:userDict]; [request startWithCompletionBlockWithSuccess:^(__kindof YTKBaseRequest * _Nonnull request) { //请求成功 //需要把头像跟用户名替换掉 [self.mtHUD hide:YES]; sleep(0.5); __weak __typeof(self) weakSelf = self; [self hudActionWithSuccessWith:@"上传成功" AfterDelay:2 successBlock:^{ self.callBackBlock(_model.data); [weakSelf mtPopback]; }]; } failure:^(__kindof YTKBaseRequest * _Nonnull request) { [self.mtHUD hide:YES]; [self hudActionWithFailWithaftAerDelay:2.0 withErrorStr:@"上传失败"]; }]; } } - (void)requestFailed:(__kindof YTKBaseRequest *)request { [self.mtHUD hide:YES]; [self hudActionWithFailWithaftAerDelay:2.0 withErrorStr:@"上传失败"]; }
上面看完了上传,再给你们来一个图片上传
老规矩还是看.h个跟.m
// // MTExerciseEditUploadRequest.h // LoveGuQin // // Created by fox on 2018/6/24. // Copyright © 2018年 Moemoe. All rights reserved. // #import "MTRequest.h" @interface MTExerciseEditUploadRequest : MTRequest - (instancetype)initWithDict:(NSDictionary *)dict; @end
在看看.m
// // MTExerciseEditUploadRequest.m // LoveGuQin // // Created by fox on 2018/6/24. // Copyright © 2018年 Moemoe. All rights reserved. // #import "MTExerciseEditUploadRequest.h" #import "AFNetWorking.h" #import "MTUserModel.h" @implementation MTExerciseEditUploadRequest { NSDictionary *_dict; } - (NSString *)requestUrl { return @"/api/exercise/edit"; } - (instancetype)initWithDict:(NSDictionary *)dict{ if (self = [super init]) { _dict = dict; } return self; } /** 重写请求参数 @return 请求参数 */ -(id)requestArgument { //可以在这里检查参数是否有带Token //如果没有这里可以补一个token // MTLog(@"%@",_dict); return _dict; } - (BOOL)statusCodeValidator { return YES; } /** 如果要添加请求头,可以实现这个方法 @return nullable = 表示可以为null */ - (nullable NSDictionary<NSString *, NSString *> *)requestHeaderFieldValueDictionary { if ([MTUserModel shareUserModel].token.length > 0 ) { NSString *token = [NSString stringWithFormat:@"Bearer %@",[MTUserModel shareUserModel].token]; return @{@"Authorization":token}; }else { return nil; } } //依旧实现这个block跟上传图片其实一样一样的.重点是,可以带参数.最终发现,initWithDict带的参数会把它拼接在body中 - (AFConstructingBlock)constructingBodyBlock { return ^(id<AFMultipartFormData> formData) { NSData *data; if ([[NSFileManager defaultManager]fileExistsAtPath:_dict[@"urlString"]]) { data = [[NSFileManager defaultManager]contentsAtPath:_dict[@"urlString"]]; if (data.length > 0) { CGFloat size = [[[NSFileManager defaultManager] attributesOfItemAtPath:_dict[@"urlString"] error:nil] fileSize]/(1024.0*1024); MTLog(@"文件大小 %f",size); } } NSString *name = _dict[@"file_id"]; NSString *formKey = @"file"; NSString *type = @"mp4/aac"; MTLog(@"%@",name); [formData appendPartWithFileData:data name:formKey fileName:name mimeType:type]; // [formData appendPartWithHeaders:_dict body:data]; }; } - (YTKRequestMethod)requestMethod { return YTKRequestMethodPOST; } @end
好了,以上这些有一些跟YTKNetwork的demo有些重合,
但是我依旧认为官方demo里给的上传的样例太少了.实际上,官方给的根本跑不通,不够全面.