摘要:
相信大家就算没有使用过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里给的上传的样例太少了.实际上,官方给的根本跑不通,不够全面.