YTKNetwork Basic Guide :YTKNetwork基本指导
In the article, we will introduce the basic usage of YTKNetwork. 在这篇文章中,我们将介绍YTKNetwork的基本用法。
YTKNetwork‘s basic composition YTKNetwork的基本组成
YTKNetwork mainly contains the following classes: YTKNetwork主要包含以下课程:
- YTKNetworkConfig :it‘s used for setting global network host address and CDN address. YTKNetworkConfig:用于设定全球网络主机地址和CDN地址。
- YTKRequest :it‘s the parent of all the detailed network request classes. All network request classes should inherit it. Every subclass of
YTKRequest
represents a specific network request. YTKRequest:父类的所有详细的网络请求。所有的网络请求应该继承它的类。每一子类YTKRequest代表一个特定的网络请求。
We will explain the above 2 classes‘ detailed usage below. 我们将解释以下2类以上的详细用法。
YTKNetworkConfig class YTKNetworkConfig类
YTKNetworkConfig class has 2 usages: YTKNetworkConfig类有两个用途:
- Set global network host address and CDN address. 建立全球网络主机地址和CDN地址。
- Manage the filters which implemented
YTKUrlFilterProtocol
protocol(we will discuss it in pro usage guide)。 管理的过滤器实现YTKUrlFilterProtocol协议(我们将讨论它在专业使用指南)。
We use YTKNetworkConfig to set global network host address because:
我们使用YTKNetworkConfig设置全球网络主机地址,因为:
- According to the
Do Not Repeat Yourself
principle,we should write the host address only once. 根据不重复自己的原则,我们应该只写一次主机地址。 - In practise, our testers need to switch host addresses at runtime. YTKNetworkConfig can satisfy such requirement. 在实践中,我们的测试人员需要在运行时切换主机地址。YTKNetworkConfig可以满足这样的要求。
We should set YTKNetworkConfig‘s property at the beggining of app launching, the sample is below:
我们应该设置YTKNetworkConfig的属性在应用程序启动的发出召唤,下面的示例:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
YTKNetworkConfig *config = [YTKNetworkConfig sharedInstance];
config.baseUrl = @"http://yuantiku.com";
config.cdnUrl = @"http://fen.bi";
}
After setting, all network requests will use YTKNetworkConfig‘s baseUrl
property as their host addresses, and they will use the cdnUrl
property of YTKNetworkConfig as their CDN addresses.
设置后,所有的网络请求将使用YTKNetworkConfig baseUrl房地产作为他们的主机地址,他们将使用cdnUrl财产YTKNetworkConfig CDN地址。
If we want to switch server address, we can just change YTKNetworkConfig‘s baseUrl
property.
如果我们想要切换服务器地址,我们可以改变YTKNetworkConfig baseUrl属性。
YTKRequest class YTKRequest 类
The design idea of YTKNetwork is that every specific network request should be a object. So after using YTKNetwork, all your request classes should inherit YTKNetwork. Through overwriting the methods of super class, you can build your own specific and distinguished request. The key idea behind this is somewhat like the Command pattern.
YTKNetwork的设计理念是,每一个特定的网络请求应该是一个对象。所以使用YTKNetwork后,所有你的要求应该继承YTKNetwork类。通过重写父类的方法,您可以构建自己的特定的和杰出的请求。这背后的关键理念有点像命令模式。
For example, if we want to send a POST request to http://www.yuantiku.com/iphone/register
,with username and password as arguments, then the class should be as following:
例如,如果我们想要发送一个POST请求到http://www.yuantiku.com/iphone/register,用户名和密码作为参数,那么类应该如下:
// RegisterApi.h
#import "YTKRequest.h"
@interface RegisterApi : YTKRequest
- (id)initWithUsername:(NSString *)username password:(NSString *)password;
@end
// RegisterApi.m
#import "RegisterApi.h"
@implementation RegisterApi {
NSString *_username;
NSString *_password;
}
- (id)initWithUsername:(NSString *)username password:(NSString *)password {
self = [super init];
if (self) {
_username = username;
_password = password;
}
return self;
}
- (NSString *)requestUrl {
// “http://www.yuantiku.com” is set in YTKNetworkConfig, so we ignore it
return @"/iphone/register";
}
- (YTKRequestMethod)requestMethod {
return YTKRequestMethodPost;
}
- (id)requestArgument {
return @{
@"username": _username,
@"password": _password
};
}
@end
In above example: 在上面的例子:
- Through overwriting
requestUrl
method, we‘ve indicated the detailed url. Bacause host address has been set inYTKNetworkConfig
, we should not write the host address inrequestUrl
method. - 通过覆盖requestUrl方法,我们表示详细的url。因为在YTKNetworkConfig主机地址,我们不应该写requestUrl主机地址的方法。
- Through overwriting
requestMethod
method, we‘ve indicated the use of thePOST
method. - 通过覆盖requestMethod方法,我们使用POST方法。
- Through overwriting
requestArgument
method, we‘ve provided thePOST
data. If argumentsusername
andpassword
contain any charaters which should be escaped, the library will do it automatically. - 通过覆盖requestArgument方法,我们提供了POST数据。如果用户名和密码参数包含任何特征应该逃,图书馆会自动。
Call RegisterApi 叫RegisterApi
OK, how can we use the RegisterApi
? We can call it in the login view controller. After initializing the instance, we can call its start
or startWithCompletionBlockWithSuccess
method to send the request to the network request queue.
好的,我们如何使用RegisterApi吗?我们可以叫它登录视图控制器。初始化实例后,可以调用它的启动或startWithCompletionBlockWithSuccess方法发送请求到网络请求队列。
Then we can get network response by block
or delegate
mechanism.
然后我们可以通过阻止或委托网络响应机制。
- (void)loginButtonPressed:(id)sender {
NSString *username = self.UserNameTextField.text;
NSString *password = self.PasswordTextField.text;
if (username.length > 0 && password.length > 0) {
RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password];
[api startWithCompletionBlockWithSuccess:^(YTKBaseRequest *request) {
// you can use self here, retain cycle won‘t happen
NSLog(@"succeed");
} failure:^(YTKBaseRequest *request) {
// you can use self here, retain cycle won‘t happen
NSLog(@"failed");
}];
}
}
Kindly be noted that you can use self
directly in the block where the retain cycle won‘t happen. Because YTKRequest will set callback block to nil, so the block will be released right after the network request completed.
请注意,您可以使用直接自我的块保留周期不会发生。因为YTKRequest将回调块为零,所以块将网络请求完成后发布。
Besides the block
callback, YTKRequest also support delegate
callback method. The example is below:
除了块回调,YTKRequest也支持委托回调方法。下面的例子是:
- (void)loginButtonPressed:(id)sender { NSString *username = self.UserNameTextField.text; NSString *password = self.PasswordTextField.text; if (username.length > 0 && password.length > 0) { RegisterApi *api = [[RegisterApi alloc] initWithUsername:username password:password]; api.delegate = self; [api start]; } } - (void)requestFinished:(YTKBaseRequest *)request { NSLog(@"succeed"); }
- (void)requestFailed:(YTKBaseRequest *)request { NSLog(@"failed"); }
Verify response JSON 验证响应JSON
The response JSON from the server cannnot be always trusted. Client may crash if the data is returned in faulty format from the server.
来自服务器的响应JSON总不会是可信的。客户可能会崩溃,如果数据从服务器返回错误的格式。
YTKRequest provides a simple way to verity the respose JSON.
YTKRequest真实性respose JSON提供了一个简单的方法。
For example, let‘s say we need to send a GET
request to http://www.yuantiku.com/iphone/users
address with a argument named userId
. The server will return the target user‘s information, including nickname and level. We shall guarantee that the response type of nickname is string and the type of level is number. To ensure this, we can overwrite the jsonValidator
as following:
举个例子,假设我们需要发送一个GET请求到http://www.yuantiku.com/iphone/users地址和一个名叫userId参数。服务器将返回目标用户的信息,包括昵称和水平。我们将保证昵称的响应类型是字符串和水平数的类型。为了确保这一点,我们可以覆盖jsonValidator如下:
- (id)jsonValidator {
return @{
@"nick": [NSString class],
@"level": [NSNumber class]
};
}
The whole code sample is below: 整个代码示例如下:
// GetUserInfoApi.h
#import "YTKRequest.h"
@interface GetUserInfoApi : YTKRequest
- (id)initWithUserId:(NSString *)userId;
@end
// GetUserInfoApi.m
#import "GetUserInfoApi.h"
@implementation GetUserInfoApi {
NSString *_userId;
}
- (id)initWithUserId:(NSString *)userId {
self = [super init];
if (self) {
_userId = userId;
}
return self;
}
- (NSString *)requestUrl {
return @"/iphone/users";
}
- (id)requestArgument {
return @{ @"id": _userId };
}
- (id)jsonValidator {
return @{
@"nick": [NSString class],
@"level": [NSNumber class]
};
}
@end
Here is some other samples:这里有一些其他的样品:
- Require return String array: 需要返回字符串数组:
- (id)jsonValidator {
return @[ [NSString class] ];
}
- Here is one complex sample from our company: 这是一个复杂的样品从我们的公司:
- (id)jsonValidator {
return @[@{
@"id": [NSNumber class],
@"imageId": [NSString class],
@"time": [NSNumber class],
@"status": [NSNumber class],
@"question": @{
@"id": [NSNumber class],
@"content": [NSString class],
@"contentType": [NSNumber class]
}
}];
}
Use CDN address 使用CDN地址
If you need to use CDN address in some of your requests, just overwrite the - (BOOL)useCDN;
method, and return YES
in the method.
如果你需要使用CDN地址在你的请求,只是覆盖——(BOOL)useCDN;方法,并返回YESin方法。
For example, if we have a interface for image downloading, and the address is http://fen.bi/image/imageId
with the host http://fen.bi
as the CDN address. Then the code should be below:
例如,如果我们有一个界面图片下载,地址是http://fen。bi /图像/ imageId与宿主http://fen。bi作为CDN地址。然后下面的代码应该是:
// GetImageApi.h
#import "YTKRequest.h"
@interface GetImageApi : YTKRequest
- (id)initWithImageId:(NSString *)imageId;
@end
// GetImageApi.m
#import "GetImageApi.h"
@implementation GetImageApi {
NSString *_imageId;
}
- (id)initWithImageId:(NSString *)imageId {
self = [super init];
if (self) {
_imageId = imageId;
}
return self;
}
- (NSString *)requestUrl {
return [NSString stringWithFormat:@"/iphone/images/%@", _imageId];
}
- (BOOL)useCDN {
return YES;
}
@end
Resumable Downloading 可恢复的下载
If you want to enable resumable downloading, you just need to overwrite the resumableDownloadPath
method and provide a temporary path to save the half-downloaded data.
如果你想使可恢复的下载,你只需要覆盖resumableDownloadPath方法和提供一个临时路径保存half-downloaded数据。
We can modify above example to support resumable downloading.
我们可以修改上面的例子来支持可恢复的下载。
@implementation GetImageApi {
NSString *_imageId;
}
- (id)initWithImageId:(NSString *)imageId {
self = [super init];
if (self) {
_imageId = imageId;
}
return self;
}
- (NSString *)requestUrl {
return [NSString stringWithFormat:@"/iphone/images/%@", _imageId];
}
- (BOOL)useCDN {
return YES;
}
- (NSString *)resumableDownloadPath {
NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cachePath = [libPath stringByAppendingPathComponent:@"Caches"];
NSString *filePath = [cachePath stringByAppendingPathComponent:_imageId];
return filePath;
}
@end
Cache response data 缓存响应数据
We‘ve implemented the GetUserInfoApi
before, which is used for getting user information.
我们已经实现了GetUserInfoApi之前,用于获取用户信息。
We may want to cache the response. In the following example, we overwrite the cacheTimeInSeconds
method, then our API will automatically cache data for specified amount of time. If the cached data is not expired, the api‘s start
and startWithCompletionBlockWithSuccess
will return cached data as a result directly.
我们可能想要缓存响应。在接下来的例子中,我们覆盖cacheTimeInSeconds方法,那么我们的API为指定的时间会自动缓存数据。如果缓存数据没有过期,api的开始和startWithCompletionBlockWithSuccess将直接返回缓存的数据结果。
@implementation GetUserInfoApi {
NSString *_userId;
}
- (id)initWithUserId:(NSString *)userId {
self = [super init];
if (self) {
_userId = userId;
}
return self;
}
- (NSString *)requestUrl {
return @"/iphone/users";
}
- (id)requestArgument {
return @{ @"id": _userId };
}
- (id)jsonValidator {
return @{
@"nick": [NSString class],
@"level": [NSNumber class]
};
}
- (NSInteger)cacheTimeInSeconds {
// cache 3 minutes, which is 60 * 3 = 180 seconds
return 60 * 3;
}
@end
The cache mechanism is transparent to the controller, which means the request caller may get the result right after invoking the request without casuing any real network traffic as long as its cached data remains valid.
缓存机制对控制器是透明的,这意味着请求调用者可能会调用请求的结果后没有因为任何真正的网络流量,只要其缓存的数据仍然有效。
The above code samples are available in the YTKNetworkDemo project.
上面的代码样本YTKNetworkDemo项目中是可用的。