今天學習了一下YTKNetwork,在此寫下心得,記錄學習歷程
首先YTKNetwork的基本功能如下:
1,YTKNetwork包含兩個類,分別是YTKNetworkConfig類和YTKRequest類,其中YTKNetworkConfig類是用于統一設置網絡請求的服務器和CDN的地址。YTKRequest類是所有的網絡請求類需要繼承于YTKRequest類,每一個YTKRequest類的子類代表一種專門的網絡請求。
其次YTKNetworkConfig類有兩個作用:1)統一設置網絡請求的服務器和CDN地址。2)管理網絡請求的YTKUrlFilterProtocol實例。
需要統一設置服務器地址是因為:1)要按照設計模式里的應該把服務器地址統一寫在一個地方。2)在實際業務中,我們的測試人員需要切換不同的服務器地址來測試。統一設置服務器地址到?YTKNetworkConfig?類中,也便于我們統一切換服務器地址。
在程序剛啟動的回調中,設置好YTKNetworkConfig的信息,代碼如下:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary?*)launchOptions
{
YTKNetworkConfig *config = [YTKNetworkConfig?sharedConfig];
config.baseUrl =?@"http://yuantiku.com";
config.cdnUrl =?@"http://fen.bi";
}
設置好之后,所有的網絡請求都會默認使用?YTKNetworkConfig?中?baseUrl?參數指定的地址。
YTKRequest類
每一種請求都需要繼承?YTKRequest?類,通過覆蓋父類的一些方法來構造指定的網絡請求,每一種網絡請求繼承?YTKRequest?類后,需要用方法覆蓋的方式,來指定網絡請求的具體信息。
例如我們要向網址?http://www.yuantiku.com/iphone/register?發送一個?POST?請求,請求參數是?username?和?password。那么,這個類應該如下所示:
#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?{
return?@"/iphone/register";
}
- (YTKRequestMethod)requestMethod?{
return?YTKRequestMethodPOST;
}
- (id)requestArgument?{
return?@{
@"username": _username,
@"password": _password
};
}
@end
在上面這個示例中,我們可以看到:
1)我們通過覆蓋?YTKRequest?類的?requestUrl?方法,實現了指定網址信息。并且只需要指定除去域名剩余的網址信息,因為域名信息在?YTKNetworkConfig?中已經設置過了。
2)我們通過覆蓋?YTKRequest?類的?requestMethod?方法,實現了指定?POST?方法來傳遞參數。
3)我們通過覆蓋?YTKRequest?類的?requestArgument?方法,提供了?POST?的信息。這里面的參數?username?和?password?如果有一些特殊字符(如中文或空格),也會被自動編碼。
調用RegisterApi
在構造完成?RegisterApi?之后,具體如何使用呢?我們可以在登錄的?ViewController?中,調用?RegisterApi,并用?block?的方式來取得網絡請求結果:
- (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) {
//?你可以直接在這里使用?self
NSLog(@"succeed");
}?failure:^(YTKBaseRequest *request) {
//?你可以直接在這里使用?self
NSLog(@"failed");
}];
}
}
注意:可以直接在?block?回調中使用?self,不用擔心循環引用。因為?YTKRequest?會在執行完?block?回調之后,將相應的?block?設置成?nil。從而打破循環引用。除了?block?的回調方式外,YTKRequest?也支持?delegate?方式的回調:
- (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");
}
驗證服務器返回內容
有些時候,由于服務器的?Bug,會造成服務器返回一些不合法的數據,如果盲目地信任這些數據,可能會造成客戶端?Crash。如果加入大量的驗證代碼,又使得編程體力活增加,費時費力。
使用?YTKRequest?的驗證服務器返回值功能,可以很大程度上節省驗證代碼的編寫時間。
例如,我們要向網址?http://www.yuantiku.com/iphone/users?發送一個?GET?請求,請求參數是?userId?。我們想獲得某一個用戶的信息,包括他的昵稱和等級,我們需要服務器必須返回昵稱(字符串類型)和等級信息(數值類型),則可以覆蓋?jsonValidator?方法,實現簡單的驗證。
- (id)jsonValidator {
return?@{
@"nick": [NSString?class],
@"level": [NSNumber?class]
};
}
完整的代碼如下:
// 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