YTK理解

2018-08-06  本文已影响0人  bliva

一、YTK的Git库地址

https://github.com/yuantiku/YTKNetwork/blob/master/Docs/BasicGuide_cn.md
里面有YTK的中文说明,以及一些场景的用法,下面我们来看一下我们项目的一些使用场景

二、基类的封装

1、我们现在所用的接口请求是在YTK的基础上在封装了一层(房信平台封装了2层,因为要加上缓存以及加密等逻辑),那房信平台的FangChaChaRequest来说,继承于EtopBaseRequest,EtopBaseRequest主要做了设置接口的请求方式(有两种请求方式,POST和GET,注上两者区别https://www.cnblogs.com/logsharing/p/8448446.html,一般都用POST(更安全));重写自定义请求头的方法,塞入请求头的样式;以及解析返回结果的格式(JSON,XML,Data三种,一般都用JSON);封装调用请求的方法;

image.png
image.png
2、下面我们看FangChaChaRequest做了什么?
(1)首先涉及加密的逻辑处理,我们要对接口的请求参数进行加密,这里的加密会每次根据App启动随机变成加密值,加密的代码附上如下图
image.png
(2)设置请求失败提示时间(一般都是15s)
- (NSTimeInterval)requestTimeoutInterval {
//    if (DEBUG) {
//        return 5;
//    }
    return 15;
}

(3)重写- (void)startWithCompletionHandlerWithSuccess:(nullable ETopRequestSuccessBlock)success failure:(nullable ETopRequestFailureBlock)failure方法,请求成功的时候先判断开没开起缓存,如果有先返回缓存数据,这里一定要注意的是如果用户开启了缓存,即使缓存成功,我们也需在重新调用一次请求方法,更新缓存,否则每次拿到的都是头一次缓存的结果;
a、请求成功


image.png

b、请求失败,拿到错误信息,判断是否是证书错误


image.png

(4)特别注意的是因为我们对请求参数进行了加密,然后YTK的缓存是把请求参数当做Key,前面有提过APP启动的时候加密会随机,这个时候我们的缓存的Key变了,我们就拿不到上一次缓存数据的值,所以,我们加密后必须在FangChaChaRequest里面重写YTK的获取Key的- (id)cacheFileNameFilterForRequestArgument:(id)argument这个方法,返回我们未加密前的请求参数

- (id)cacheFileNameFilterForRequestArgument:(id)argument {
    if ((NSNull *)self.unEncryptorArgument != [NSNull null] && self.unEncryptorArgument.count > 0) {
        return self.unEncryptorArgument;
    } else {
        return argument;
    }
}

三、应用场景

1、缓存使用

在上面封装完毕后,只需要在我们的API文件中,重写- (NSInteger)cacheTimeInSeconds这个方法,并设置你想要缓存的时间(一般我们返回最大值)

- (NSInteger)cacheTimeInSeconds {
    return NSIntegerMax;
}

2、异步请求

(1)YTK的异步请求适用于两个接口之间没什么依赖;但是YTK的异步请求会有一个接口请求失败,接口就返回失败;正常来说,逻辑也应该这么处理,虽然两个接口没有依赖,但是如果一个界面有两个接口,又是异步请求,如果不知道那个接口先回来,布局比较麻烦,所以还是一个接口接口失败直接失败处理比较好;最先我不会YTK的异步请求的时候写了一个非常low的请求方法(捂脸),block里面调用block,请求成功调用一次,失败在调用一次


image.png

所以使用YTK的异步请求后,我们只需要调用一个方法,也不需要写这么多回调的block


image.png

(2)值得注意的是我们也在YTK的异步请求YTKBatchRequest做了一层我们项目逻辑的封装FangChaChaBatchRequest,因为如果我们直接调用YTKBatchRequest,这个时候我们一些成功回调里面返回的其他状态码不会判断,所以我们要在YTK的基础上封装一层加上我们逻辑处理的基类

- (void)startWithCompletionHandlerWithSuccess:(nullable ETopBatchCompletionBlock)success failure:(nullable ETopBatchCompletionBlock)failure {
    [super startWithCompletionBlockWithSuccess:^(YTKBatchRequest *_Nonnull batchRequest) {
        for (YTKRequest *request in batchRequest.requestArray) {
            id responseObjec = [request responseJSONObject];
            NSInteger statusCode = [responseObjec[@"StatsCode"] integerValue];
            statusCode = (statusCode == 0 ? [responseObjec[@"status"] integerValue] : statusCode);
            if (statusCode == SUCCEEDED_BatchRequest) {
                if (success) {
                    success((ETopBatchRequest *)batchRequest);
                }
            } else {
                if (statusCode == LoginFailCodeType) {
                    // 清空用户信息
                    [LoginManager saveUserModel:nil];
                } else if (statusCode == AuthorizationFailedCodeType) {
                    NSLog(@"重新获取token");
                    [[DDOAuthClient shareInstance] getTokenAndLoginWithSuccess:nil];
                }
                if (failure) {
                    NSString *message = request.responseObject[@"Message"];
                    message = message ?: request.responseObject[@"msg"];
                    failure((ETopBatchRequest *)batchRequest);
                }
            }
        }        
    }
        failure:^(YTKBatchRequest *_Nonnull batchRequest) {
            if (failure) {
                // 失败
                NSString *description = batchRequest.failedRequest.error.localizedDescription;
                description = [description stringByReplacingOccurrencesOfString:@"." withString:@""];
                description = [description stringByReplacingOccurrencesOfString:@"。" withString:@""];
                if (batchRequest.failedRequest.error.localizedRecoverySuggestion) { // 证书错误
                    NSData *errorData = [[NSData alloc] initWithData:[batchRequest.failedRequest.error.localizedRecoverySuggestion dataUsingEncoding:NSUTF8StringEncoding]];
                    NSDictionary *recoverySuggestion = [NSJSONSerialization JSONObjectWithData:errorData options:NSJSONReadingMutableLeaves error:nil];
                    if (recoverySuggestion) {
                        NSString *message = recoverySuggestion[@"Message"];
                        message = message ?: recoverySuggestion[@"msg"];
                        description = message;
                    }
                }
                failure((ETopBatchRequest *)batchRequest);
            }
        }];
}

3、同步请求

(1)同步请求适用于两个接口直接存在依赖,第二个接口请求的参数必须从第一个接口请求成功后的结果而来,前面也提到过,我们请求的时候有自己的状态码逻辑处理,所以同理异步请求我们也需要做一层基于YTKChainRequest的封装;同步请求不像异步请求,它的返回回调是两个代理方法- (void)chainRequestFinished:(YTKChainRequest *)chainRequest(完成的代理方法),- (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest *)request (失败的代理方法),所以我们在封装的时候首页要遵循代理,设置代理为自己以及请求成功和失败的回调,在请求成功后我们返回请求成功的block,失败的时候判断失败的错误,并返回失败的回调
a、初始化,遵循代理

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.delegate = self;
    }
    return self;
}

b、调用父类的同步请求方法,回调请求数据

- (void)addYTRequest:(ETopBaseRequest *)request callback:(nullable ETopChainCallback)callback{
    [super addRequest:request callback:^(YTKChainRequest * _Nonnull chainRequest, YTKBaseRequest * _Nonnull baseRequest) {
        if (callback) {
            callback((ETopChainRequest *)chainRequest,(ETopBaseRequest *)baseRequest);
        }
    }];
}

c、实现请求成功的代理方法,加上项目的状态码等逻辑判断,并且回调请求成功的数据

- (void)chainRequestFinished:(YTKChainRequest *)chainRequest {

    for (YTKBaseRequest *request in chainRequest.requestArray) {
        id responseObjec = [request responseJSONObject];
        NSInteger statusCode = [responseObjec[@"StatsCode"] integerValue];
        statusCode = (statusCode == 0 ? [responseObjec[@"status"] integerValue] : statusCode);
        if (statusCode == SUCCEED_ChainRequest) {
            if (self.ChainRequestSuccessBlock) {
                self.ChainRequestSuccessBlock((ETopChainRequest *)chainRequest);
            }
        } else {
            if (statusCode == LoginFailCodeType) {
                // 清空用户信息
                [LoginManager saveUserModel:nil];
            } else if (statusCode == AuthorizationFailedCodeType) {
                NSLog(@"重新获取token");
                [[DDOAuthClient shareInstance] getTokenAndLoginWithSuccess:nil];
            }
            if (self.ChainRequestFailureBlock) {
                NSString *message = request.responseObject[@"Message"];
                message = message ?: request.responseObject[@"msg"];
                self.ChainRequestFailureBlock((ETopChainRequest *)chainRequest, message);
            }
        }
    }
}

b、实现请求失败的代理,判断是否是证书错误的逻辑判断,并且返回失败的数据和提示

- (void)chainRequestFailed:(YTKChainRequest *)chainRequest failedBaseRequest:(YTKBaseRequest *)request {
    // 失败
    NSString *description = request.error.localizedDescription;
    description = [description stringByReplacingOccurrencesOfString:@"." withString:@""];
    description = [description stringByReplacingOccurrencesOfString:@"。" withString:@""];
    if (request.error.localizedRecoverySuggestion) { // 证书错误
        NSData *errorData = [[NSData alloc] initWithData:[request.error.localizedRecoverySuggestion dataUsingEncoding:NSUTF8StringEncoding]];
        NSDictionary *recoverySuggestion = [NSJSONSerialization JSONObjectWithData:errorData options:NSJSONReadingMutableLeaves error:nil];
        if (recoverySuggestion) {
            NSString *message = recoverySuggestion[@"Message"];
            message = message ?: recoverySuggestion[@"msg"];
            description = message;
        }
    }
    self.ChainRequestFailureBlock((ETopChainRequest *)chainRequest, description);
}

(2)具体使用方法
请求数据,(两个接口直接一定具有依赖性,这里只是举例,其实举例的这两个接口没有啥依赖)


image.png

a、请求失败的处理


image.png

b、请求成功,UI布局


image.png

4、YTK的文件流上传功能

我们可以通过重写constructingBodyBlock的方法,来实现上传(例如我们上传语音和图片),我们项目中的UploadFileAPI接口有用到

- (AFConstructingBlock)constructingBodyBlock {
    return ^(id<AFMultipartFormData> formData) {
        for (UploadFileModel *model in _fileModelsArray) {
            [formData appendPartWithFileData:model.data name:model.fileName fileName:model.fileName mimeType:@""];
        }
    };
}

5、断点续传

要启动断点续传功能,我们只需要覆盖resumableDownloadPath方法,指定断点续传时文件的存储路径即可,文件会被自动保存到此路径;(项目暂时没有用到,这里现附上YTK的用例,假设我们需要从服务器下载一张图片到本地)

- (NSString *)resumableDownloadPath {
    NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *cachePath = [libPath stringByAppendingPathComponent:@"Caches"];
    NSString *filePath = [cachePath stringByAppendingPathComponent:_imageId];
    return filePath;
}

总结

YTK隔离出了业务逻辑层,一些小的方法比较省代码,会提高效率

上一篇下一篇

猜你喜欢

热点阅读