我对 Objective-C 和 iOS 开发有点陌生(使用它大约 1.5 年,实际上只是最近 8 个月左右才开始大量参与)。我编写了一个自定义类来处理我所有的网络服务请求。我使用AFNetworking处理这些请求(并且喜欢它),但我想确保我所做的事情是高效的,并且不会在以后引起问题。
从我在 Instruments 中看到的以及应用程序的性能来看,这似乎是一个很好的方法,但我真的远非专家,我希望得到一些反馈和/或建议。
这是我的 NetworkClient 类:
网络客户端.h:
#import <Foundation/Foundation.h>
extern NSString * const APIKey;
@interface NetworkClient : NSObject
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block;
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block;
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block;
+(void)handleNetworkErrorWithError:(NSError *)error;
+(void)handleNoAccessWithReason:(NSString *)reason;
@end
网络客户端.m:
#import "NetworkClient.h"
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"
#import "SBJson.h"
NSString * const APIKey = @"MyAPIKeyThatIsDefinedInDatabasePerApplication";
@implementation NetworkClient
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
block:(void (^)(id obj))block {
[self processURLRequestWithURL:url andParams:params syncRequest:NO alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
block:(void (^)(id obj))block {
[self processURLRequestWithURL:url andParams:params syncRequest:syncRequest alertUserOnFailure:NO block:^(id obj) {
block(obj);
}];
}
+(void)processURLRequestWithURL:(NSString *)url
andParams:(NSDictionary *)params
syncRequest:(BOOL)syncRequest
alertUserOnFailure:(BOOL)alertUserOnFailure
block:(void (^)(id obj))block {
// Default url goes here, pass in a nil to use it
if (url == nil) {
url = @"https://MyURLToWebService";
}
// Add in our API Key
NSMutableDictionary *newParams = [[NSMutableDictionary alloc] initWithDictionary:params];
[newParams setValue:APIKey forKey:@"APIKey"];
NSURL *requestURL;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL];
NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:url parameters:newParams];
__block NSString *responseString = @"";
AFHTTPRequestOperation *_operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
__weak AFHTTPRequestOperation *operation = _operation;
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
responseString = [operation responseString];
id retObj = [responseString JSONValue];
// Check for invalid response (No Access)
if ([retObj isKindOfClass:[NSDictionary class]]) {
if ([[(NSDictionary *)retObj valueForKey:@"Message"] isEqualToString:@"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
}
} else if ([retObj isKindOfClass:[NSArray class]]) {
if ([(NSArray *)retObj count] > 0) {
NSDictionary *dict = [(NSArray *)retObj objectAtIndex:0];
if ([[dict valueForKey:@"Message"] isEqualToString:@"No Access"]) {
block(nil);
[self handleNoAccessWithReason:[(NSDictionary *)retObj valueForKey:@"Reason"]];
}
}
}
block(retObj);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failed with error = %@", [NSString stringWithFormat:@"[Error]:%@",error]);
block(nil);
if (alertUserOnFailure) {
// Let the user know something went wrong
[self handleNetworkErrorWithError:operation.error];
}
}];
[operation start];
if (syncRequest) {
// Process the request syncronously
[operation waitUntilFinished];
}
}
+(void)handleNetworkErrorWithError:(NSError *)error {
NSString *errorString = [NSString stringWithFormat:@"[Error]:%@",error];
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:@"Connection Error"
message:errorString
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
[myAlert show];
}
+(void)handleNoAccessWithReason:(NSString *)reason {
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:@"No Access"
message:reason
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
[myAlert show];
}
@end
这就是我所说的:
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
@"GetApplications", @"Command",
userInfo.networkID, @"NetworkID",
nil];
[NetworkClient processURLRequestWithURL:nil andParams:params block:^(id obj) {
[MBProgressHUD hideHUDForView:self.view animated:YES];
if ([obj isKindOfClass:[NSArray class]]) {
myTableViewData = (NSArray *)obj;
[self.myTableView reloadData];
}
}];
所以我的网络服务可以发送回一个字典结构的 JSON 响应和一个数组格式的 JSON 响应。NetworkClient 方法将同时接收并发送回它所获得的内容(我将其留给调用代码以确保它返回预期的内容)。我使用 APIKey 作为额外的安全措施,以确保只有我的应用程序可以访问 Web 服务资源(在发回数据之前我检查的第一件事是 APIKey 与我在数据库中为该应用程序所拥有的匹配)。
这是做这种事情的有效方法吗?有什么办法让它变得更好吗?