一个简单灵活的基于 JSON 的 iOS API 客户端。
NTApiClient 旨在用作您自己的 JSON API 的基类。NTApiClient 最终使用 NSURLRequest 执行其处理。请求处理在后台线程上处理,您的响应处理可以是后台线程、主线程或启动请求的线程(当前线程)。
该系统的核心是通过一个 NTApiArgs 数组(论证可能是简单项目,如 URL 论证或表单参数)进行控制的。NTApiArgs 还可用于设置标头或控制整体请求,例如超时或处理响应的线程。因为这是一个可以构建和处理的数组,它提供了大量的灵活性。您可以认为论证数组是一个非常特定的 DSL。以下 NTArgs 支持
NTApiUrlArg
- 查询字符串值NTApiFormArg
- 表单值(POST 语义)NTApiMultipartArg
- 多部分附件NTApiRawDataArg
- 发送不需要额外处理的数据NTApiBaseUrlArg
- 覆盖默认的 baseUrlNTApiHeaderArg
- 标头值NTApiBasicAuthArg
- 基本认证标头NTApiOptionArg
- 设置多个整体选项,包括使用的线程模型。NTApiTimeoutArg
- 覆盖默认的超时NTApiHttpMethodArg
- 覆盖默认的 HTTP 方法。NTApiCachePolicyArg
- 覆盖默认的缓存策略。默认值允许您设置可能根据请求覆盖的全局值。这是一个设置类似于请求的 baseUrl 等值非常方便的方法。此外,可以通过协议实现默认值以提供“动态”默认值,例如会话 ID。
每个请求都使用多个线程进行处理
NSURLRequest
)NSURLRequest
代理处理在一个共享的后台线程(NTApiRequestThread)上处理。此处理限于捕获下载数据、捕获错误等。如果已设置上传或下载进度处理程序,这些将在指示的线程上调用 - 而不是 NTApiRequestThread。对于每一个请求,都会启动一个iOS后台任务,该任务会持续到你的responseHandler函数返回,所以即使应用程序进入后台状态,你的任务也应该可以正常完成。
良好的日志记录对API来说非常重要。默认情况下,NTApi会将消息通过-overridable方法 -(void)writeLogWithType:andFormat:记录到NSLog中。你可以重写这个方法以记录到你喜欢的日志子系统。此外,如果你使用CocoaPods并安装了NTLog,NTAPIClient将自动使用它。你也可以通过宏禁用所有日志。(参见NTAPI_LOG_*宏。)如果你感兴趣,可以查看NTLog的配置并发送一个Pull Request!
你可以使用logFlags属性编程控制记录的内容。这可以针对每个实例设置,也可以使用“logFlags”默认值全局设置。
1.10 - 2014年3月14日 添加了对自签名SSL证书的支持,使用 arg [NTApiOptionArg optionAllowInvalidSSLCert:YES]
。
1.00 - 2014年2月7日 第一版提交到cocoapods。添加了文档和不错的示例。
只需将Core
文件夹中的文件添加到你的项目中,就可以享受它了!
NTApiClient被设计为可以继承来自定义API。你可以查看示例应用程序以获得如何做的良好示例。所有对NTApiClient的困难工作都是通过beginRequest:方法来完成的 - 你通常会想要用处理你共享API逻辑的方法来包装这个方法。实际上,我推荐使用两个方法,如下所示
-(NTApiRequest *)beginDirectRequest:(NSString *)command args:(NSArray *)args responseHandler:(void (^)(NSDictionary *data, NTApiError *error))responseHandler
{
// This method should do whatever is common to ALL requests - generally extracting error messages or adding args that are common to all requests.
NTApiRequest *request = [self beginRequest:command args:args responseHandler:^(NTApiResponse *response)
{
NTApiError *error = response.error;
// If there wasn't a system error, see if we can find an error from the API and instantiate it...
if ( !error )
{
/// TODO: Extract any API error code that was returned
}
responseHandler(response.json, error);
}];
return request;
}
-(NTApiRequest *)beginStdRequest:(NSString *)command args:(NSArray *)args responseHandler:(void (^)(NSDictionary *data, NTApiError *error))responseHandler
{
// This method should handle items that are generally common to requests. It may add standard parameters such
// as a session token or even make multiple API calls to do something like re-authenticate transparently. It should
// make one or more calls to beginDirectRequest.
return [self beginDirectRequest:command args:args responseHandler:responseHandler];
}
你的API方法通常应该调用beginStdRequest来利用你的标准请求处理。以下是一个示例应用程序中API方法的示例,以供你参考。我们在将响应解析到我们的业务对象中并返回它们。
-(NTApiRequest *)beginFindCitiesWithName:(NSString *)cityName searchType:(OpenWeatherSearchType)searchType maxItems:(int)maxItems responseHandler:(void (^)(NSArray *currentWeatherItems, NTApiError *error))responseHandler
{
return [self beginStdRequest:@"find"
args:@[
[NTApiUrlArg argWithName:@"q" string:cityName],
[NTApiUrlArg argWithName:@"type" string:searchType],
[NTApiUrlArg argWithName:@"cnt" intValue:maxItems],
]
responseHandler:^(NSDictionary *data, NTApiError *error)
{
NSArray *currentWeatherItems = nil;
if ( data )
{
NSArray *jsonItems = [data arrayForKey:@"list"];
currentWeatherItems = [CurrentWeather itemArrayWithJsonArray:jsonItems];
}
responseHandler(currentWeatherItems, error);
}];
}
你可以在init方法中加载它们的默认值来实施你自己的默认设置。这允许客户端代码根据需要在每个API客户端实例的基础上覆盖它们。此示例也来自示例应用程序。
-(id)init
{
self = [super init];
if ( self )
{
self.appid = [self.class getDefault:@"appid"];
}
return self;
}
如果你希望将你的API错误代码转换为“NSString enum's”,你可以通过NTApiError将它们注册。这将自动将它们转换为你的常量值,这样你就可以使用==代替isEqualToString:
。最佳做法是在`+load`方法中这样做
+(void)load
{
[NTApiError addErrorCode:OpenWeatherErrorCodeNotFound];
}
通常,你希望在应用程序启动时将API服务器等配置为默认值。这可以在你的AppDelegate的didFinishLoadingWithOptions
中完成,如下所示
[OpenWeatherApiClient setDefault:@"baseUrl" value:@"http://api.openweathermap.org/data/2.5"];
[OpenWeatherApiClient setDefault:@"appid" value:OPENWEATHER_APPID];
使用API非常直接,以下是一个示例。(注意,这假设有一个助手来创建实例 - +apiClient
)
[[OpenWeatherApiClient apiClient] beginFindCitiesWithName:cityName
searchType:OpenWeatherSearchTypeLike
maxItems:20
responseHandler:^(NSArray *currentWeatherItems, NTApiError *error)
{
if ( error ) // display API errors
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error getting weather"
message:error.errorMessage
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
return ;
}
self.currentWeatherItems = currentWeatherItems;
[self.tableView reloadData];
}];