This commit is contained in:
2022-03-21 11:16:38 +08:00
commit e89e807c64
1040 changed files with 284164 additions and 0 deletions
@@ -0,0 +1,14 @@
//
// AFNPhalApiClient.h
// PhalApiClientDemo
//
// Created by Aevit on 15/10/18.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import "PhalApiClient.h"
#import "AFHTTPRequestOperationManager.h"
@interface AFNPhalApiClient : PhalApiClient
@end
@@ -0,0 +1,101 @@
//
// AFNPhalApiClient.m
// PhalApiClientDemo
//
// Created by Aevit on 15/10/18.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import "AFNPhalApiClient.h"
#import "PhalApiClientFilter.h"
@implementation AFNPhalApiClient
#pragma mark - generate a client
/**
* 生成单例
*
* @return 单例PhalApiClient
*/
+ (AFNPhalApiClient*)sharedClient {
static AFNPhalApiClient *_sharedClient;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[AFNPhalApiClient alloc] init];
});
return _sharedClient;
}
/**
* 生成非单例
*
* @return 非单例PhalApiClient
*/
+ (AFNPhalApiClient*)create {
AFNPhalApiClient *client = [[AFNPhalApiClient alloc] init];
return client;
}
#pragma mark - request
/**
* 发起接口请求(POST请求)
*
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)request:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock {
return [self requestWithFormDataBlock:nil completeBlock:completeBlock failureBlock:failureBlock];
}
/**
* 发起接口请求(提交表单)
*
* @param formDataBlock 表单内容
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)requestWithFormDataBlock:(FormDataBlock)formDataBlock completeBlock:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock {
if (self.filter) {
// 过滤器,可生成签名验证等
[self.filter filter:self.service params:self.params];
}
NSString *url = self.host;
if (self.service && self.service.length > 0) {
// 一般来说,建议service以GET方式写在url里,其他所有参数,统一用POST方式
url = [NSString stringWithFormat:@"%@?service=%@", self.host, self.service];
}
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", @"text/plain", @"text/json", @"text/xml", nil];
manager.requestSerializer.timeoutInterval = self.timeout;
AFHTTPRequestOperation *operation = [manager POST:url parameters:self.params constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
if (formDataBlock) {
formDataBlock(formData);
}
} success:^(AFHTTPRequestOperation * _Nonnull operation, id _Nonnull responseObject) {
// 默认以JSON返回,如需其他格式(如XML,请上google搜索"AFNetworking XML"相关资料即可)
if (completeBlock) {
completeBlock(responseObject);
}
} failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {
if (error.code == NSURLErrorTimedOut) {
NSDictionary *timeoutDict = @{@"ret": @408, @"data": @{}, @"msg": @"Request Timeout"};
failureBlock(timeoutDict);
return ;
}
if (failureBlock) {
failureBlock(error);
}
}];
return operation;
}
@end
@@ -0,0 +1,131 @@
//
// PhalApiClient.h
// PhalApiClientDemo
//
// Created by Aevit on 15/10/17.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "PhalApiClientFilter.h"
#if 1
# define PALog(x, ...) NSLog(x, ## __VA_ARGS__);
#else
# define PALog(x, ...)
#endif
typedef void(^HttpCompleteBlock)(id resultObject);
typedef void(^HttpFailureBlock)(id error);
typedef void(^FormDataBlock)(id formData);
@interface PhalApiClient : NSObject
@property (nonatomic, copy) NSString *host;
@property (nonatomic, copy) NSString *service;
@property (nonatomic, strong) NSMutableDictionary *params;
@property (nonatomic, assign) float timeout;
@property (nonatomic, strong) PhalApiClientFilter *filter;
#pragma mark - generate a client
/**
* 生成单例
*
* @return 单例PhalApiClient
*/
+ (PhalApiClient*)sharedClient;
/**
* 生成非单例
*
* @return 非单例PhalApiClient
*/
+ (PhalApiClient*)create;
#pragma mark - configure url and params
/**
* 重复查询时须重置请求状态,包括接口服务名称、接口参数和超时时间
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)reset;
/**
* 设置接口域名
* 如果整个客户端只有一个接口host,可以在"commonInit"方法设置好host,这样外部就可以不用调用withHost方法了
*
* @param host 域名
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withHost:(NSString*)host;
/**
* 设置将在调用的接口服务名称,如:Default.Index
*
* @param service 接口服务名称
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withService:(NSString*)service;
/**
* 设置接口参数,此方法是唯一一个可以多次调用并累加参数的操作
*
* @param params 参数
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withParams:(NSDictionary*)params;
/**
* 设置过滤器,与服务器的DI().filter对应
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withFilter:(PhalApiClientFilter*)filter;
/**
* 设置超时时间,单位毫秒
*
* @param timeout 超时时间,单位秒
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withTimeout:(float)timeout;
#pragma mark - request
/**
* 发起接口请求(POST请求)
*
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)request:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock;
/**
* 发起接口请求(提交表单)
*
* @param formDataBlock 表单内容
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)requestWithFormDataBlock:(FormDataBlock)formDataBlock completeBlock:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock;
#pragma mark - utils
/**
* 以get形式打印整个url,方便服务端开发人员调试
*
* @return 整个url
*/
- (NSString*)printTotalUrlStr;
@end
@@ -0,0 +1,226 @@
//
// PhalApiClient.m
// PhalApiClientDemo
//
// Created by Aevit on 15/10/17.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import "PhalApiClient.h"
@interface PhalApiClient()
@end
@implementation PhalApiClient
- (instancetype)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
[self reset];
/**
* 如果整个客户端只有一个接口host,可以在reset后设置好host,这样外部就可以不用调用withHost方法了
* e.g. [self withHost:@"http://api.your_host.com/project_name/"];
*/
}
#pragma mark - generate a client
/**
* 生成单例
*
* @return 单例PhalApiClient
*/
+ (PhalApiClient*)sharedClient {
static PhalApiClient *_sharedClient;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[PhalApiClient alloc] init];
});
return _sharedClient;
}
/**
* 生成非单例
*
* @return 非单例PhalApiClient
*/
+ (PhalApiClient*)create {
PhalApiClient *client = [[PhalApiClient alloc] init];
return client;
}
#pragma mark - configure url and params
/**
* 重复查询时须重置请求状态,包括接口服务名称、接口参数和超时时间
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)reset {
self.host = nil;
self.service = nil;
self.params = nil;
self.timeout = 0;
return self;
}
/**
* 设置接口域名
* 如果整个客户端只有一个接口host,可以在"commonInit"方法设置好host,这样外部就可以不用调用withHost方法了
*
* @param host 域名
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withHost:(NSString*)host {
self.host = nil;
self.host = host;
return self;
}
- (NSString *)host {
if ([[_host substringFromIndex:(_host.length - 1)] isEqualToString:@"/"]) {
return _host;
}
_host = [NSString stringWithFormat:@"%@/", _host];
return _host;
}
/**
* 设置将在调用的接口服务名称,如:Default.Index
*
* @param service 接口服务名称
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withService:(NSString*)service {
self.service = nil;
self.service = service;
return self;
}
/**
* 设置接口参数,此方法是唯一一个可以多次调用并累加参数的操作
*
* @param params 参数
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withParams:(NSDictionary*)params {
self.params = nil;
if (!params) {
return self;
}
self.params = [NSMutableDictionary dictionaryWithDictionary:params];
return self;
}
/**
* 设置过滤器,与服务器的DI().filter对应
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withFilter:(PhalApiClientFilter*)filter {
self.filter = filter;
return self;
}
/**
* 设置超时时间,单位毫秒
*
* @param timeout 超时时间,单位秒
*
* @return PhalApiClient实例
*/
- (PhalApiClient*)withTimeout:(float)timeout {
self.timeout = timeout;
return self;
}
- (float)timeout {
// 默认60s超时
return (_timeout > 0 ? _timeout : 60);
}
#pragma mark - request
/**
* 发起接口请求(POST请求)
*
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)request:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock {
/**
* 请求方式,可以使用系统的NSURLSession,或第三方的网络请求库等
* 这里我们使用第三方的AFNetworking,进行二次封装(https://github.com/AFNetworking/AFNetworking
* 新建子类(AFNPhalApiClient,继承自PhalApiClient),重写此request方法
* 如需使用其他网络请求方式(如NSURLSession),请继承自PhalApiClient,重写此request即可,可参考AFNPhalApiClient
*/
return [self requestWithFormDataBlock:nil completeBlock:completeBlock failureBlock:failureBlock];
}
/**
* 发起接口请求(提交表单)
*
* @param formDataBlock 表单内容
* @param completeBlock 请求成功的回调
* @param failureBlock 请求失败的回调
*
* @return 请求实例
*/
- (id)requestWithFormDataBlock:(FormDataBlock)formDataBlock completeBlock:(HttpCompleteBlock)completeBlock failureBlock:(HttpFailureBlock)failureBlock {
/**
* 请求方式,可以使用系统的NSURLSession,第三方的网络请求库等
* 这里我们使用第三方的AFNetworking,进行二次封装(https://github.com/AFNetworking/AFNetworking
* 新建子类(AFNPhalApiClient,继承自PhalApiClient),重写此request方法
* 如需使用其他网络请求方式(如NSURLSession),请继承自PhalApiClient,重写此request即可,可参考AFNPhalApiClient
*/
return nil;
}
#pragma mark - utils
/**
* 以get形式打印整个url,方便服务端开发人员调试
*
* @return 整个url
*/
- (NSString*)printTotalUrlStr {
if (!_host || _host.length <= 0) {
return @"empty host";
}
NSMutableString *finalStr = [NSMutableString stringWithString:_host];
[finalStr appendFormat:@"?service=%@&", _service];
if (_params) {
for (NSString *key in [_params allKeys]) {
[finalStr appendString:key];
[finalStr appendString:@"="];
id value = [_params objectForKey:key];
NSString *valueStr = @"";
if ([value isKindOfClass:[NSNumber class]]) {
valueStr = [value stringValue];
} else if ([value isKindOfClass:[NSString class]]) {
valueStr = value;
} else {
PALog(@"什么鬼?!");
}
[finalStr appendString:valueStr];
[finalStr appendString:@"&"];
}
}
return [finalStr substringWithRange:NSMakeRange(0, finalStr.length - 1)];
}
@end
@@ -0,0 +1,22 @@
//
// PhalApiClientFilter.h
// PhalApiClientDemo
//
// Created by Aevit on 15/10/18.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface PhalApiClientFilter : NSObject
/**
* 接口过滤器
* 可用于接口签名生成
*
* @param service 接口服务名称
* @param params 接口参数,注意是mutable变量,可以直接修改
*/
- (void)filter:(NSString*)service params:(NSMutableDictionary*)params;
@end
@@ -0,0 +1,24 @@
//
// PhalApiClientFilter.m
// PhalApiClientDemo
//
// Created by Aevit on 15/10/18.
// Copyright © 2015年 Aevit. All rights reserved.
//
#import "PhalApiClientFilter.h"
@implementation PhalApiClientFilter
/**
* 接口过滤器
* 可用于接口签名生成
*
* @param service 接口服务名称
* @param params 接口参数,注意是mutable变量,可以直接修改
*/
- (void)filter:(NSString*)service params:(NSMutableDictionary*)params {
// 在此对接口进行过滤
}
@end
+97
View File
@@ -0,0 +1,97 @@
```
该文档由 @Aevit 提供
```
## 使用说明
将框架目录下的 ./SDK/Objective-C/ 目录中的全部代码拷贝到项目里面即可使用。如:
![](http://aevit.qiniudn.com/PhalApiClient-SDK-files.jpeg)
```
请求方式,可以使用系统的NSURLSession,或第三方的网络请求库等
这里我们使用第三方的AFNetworking,进行二次封装(https://github.com/AFNetworking/AFNetworking
如需使用其他网络请求方式(如官方的NSURLSession),请继承自PhalApiClient,重写request方法即可,可参考AFNPhalApiClient
```
## 代码示例
如下是使用的代码场景片段。
首先,我们需要导入SDK包:
```Objective-C
#import "AFNPhalApiClient.h"
```
然后,准备按以下方法实现接口请求即可:
```Objective-C
// 待POST的参数
NSDictionary *params = @{@"demo_key_1": @"your_key", @"demo_key_2": @"1.0"};
// 使用AFNPhalApiClient
[[[[[AFNPhalApiClient sharedClient] withHost:@"http://api1.aevit.xyz/"] withService:@"Default.Index"] withParams:params] requestWithFormDataBlock:^(id formData) {
// 如需上传文件(图片等),请参照如下格式
[formData appendPartWithFileData:UIImageJPEGRepresentation([UIImage imageNamed:@"head.JPG"], 1) name:@"file" fileName:@"image.jpg" mimeType:@"image/jpeg"];
} completeBlock:^(id resultObject) {
PALog(@"resultObject: %@", resultObject);
} failureBlock:^(NSError *error) {
PALog(@"error: %@", error);
}];
// 打印url查看
PALog(@"total url: %@", [[AFNPhalApiClient sharedClient] printTotalUrlStr]);
```
## 运行效果
运行后,查询log,可以看到:
![](http://aevit.qiniudn.com/PhalApiClient-SDK-demo-result.jpg)
可以注意到,调用完成后,会有接口请求的链接和返回的结果,如:
```
2015-10-19 18:28:01.503 PhalApiClientDemo[23161:1199740] total url: http://api1.aevit.xyz/?service=Default.Index&amp;demo_key_2=1.0&amp;demo_key_1=your_key
2015-10-19 18:28:01.536 PhalApiClientDemo[23161:1199740] resultObject: {
data = {
content = "PHPer\U60a8\U597d\Uff0c\U6b22\U8fce\U4f7f\U7528PhalApi\Uff01";
time = 1445250481;
title = "Hello World!";
version = "1.2.1";
};
msg = "";
ret = 200;
}
```
## 扩展你的过滤器和结果解析器
### (1)扩展过滤器
当服务端接口需要接口签名验证,或者接口参数加密传送,或者压缩传送时,可以实现此过滤器,以便和服务端操持一致。
当需要扩展时,分两步。首先,需要实现过滤器接口:
```Objective-C
@interface MyFilter : PhalApiClientFilter
@end
@implementation PhalApiClientFilter
/**
* 接口过滤器
* 可用于接口签名生成
*
* @param service 接口服务名称
* @param params 接口参数,注意是mutable变量,可以直接修改
*/
- (void)filter:(NSString*)service params:(NSMutableDictionary*)params {
// 在此对接口进行过滤
}
@end
```
然后设置过滤器:
```Objective-C
[[[[[[AFNPhalApiClient sharedClient] withHost:@"http://api1.aevit.xyz/"] withService:@"Default.Index"] withParams:params]
withFilter:[MyFilter new]] // filter
requestWithFormDataBlock:^(id formData) {
} completeBlock:^(id resultObject) {
} failureBlock:^(NSError *error) {
}];
```
### (2)扩展结果解析器
当返回的接口结果不是JSON格式时,如XML,请上google搜索“AFNetworking XML”相关资料即可。