我正在为 iphone 和 ipad 构建一个新应用程序,我需要知道与我的 API 通信的最佳实践,通常我会在每个视图中调用 API 1 次或多次。我发现我应该使用NSURLConnection
但在处理多个连接时特别分配委托self
将使组织任务和连接成为一个非常困难的非组织过程。
以前有人遇到过这个问题吗?最佳做法是什么?我应该创建 1 个类来处理所有请求吗?
谢谢
虽然理解 NSURLConnection 很有用,但(你需要)没有必要重新发明轮子。
只需使用AFNetworking。它是异步的,易于使用,并且您会获得不错的附加功能,例如状态栏中的网络活动微调器会在有网络活动时显示。
我很久以前就经历过这个教条,解决方案是使用 blocks 和AFNetworking。
使用块的优点是它允许从同一个控制器调用相同的 API,而无需区分每个调用,因为每个调用都有自己的要执行的块。
如果您需要此类应用程序的完整架构,只需遵循基本的 OOP 原则,将网络通信逻辑分离到一个单例类(AFHTTPClient 的扩展)中,然后可以从模型类中调用,如果是数据密集型应用程序或控制器。
我创建的示例客户端扩展如下。
#import <Foundation/Foundation.h>
#import <AFNetworking.h>
@interface CRLClient : AFHTTPClient
+ (CRLClient*) sharedClient;
+ (void) setBaseURL:(NSString*)url;
- (void) uploadFiles:(NSArray*)files
path:(NSString*)path
parameters:(NSDictionary*)parameters
progressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block
success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure;
@end
#import "CRLClient.h"
@implementation CRLClient
static NSString *CRLBaseURL = nil;
+ (void) setBaseURL:(NSString*)url;
{
CRLBaseURL = [url copy];
}
+ (CRLClient*) sharedClient
{
static CRLClient* sharedInstance = nil;
// dispatch_once_t dispOnce;
@synchronized (sharedInstance) {
if (!sharedInstance) {
// dispatch_once(&dispOnce, ^{
sharedInstance = [[CRLClient alloc] initWithBaseURL:[NSURL URLWithString:CRLBaseURL]];
}
// });
}
return sharedInstance;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:@"Accept" value:@"application/json"];
self.parameterEncoding = AFJSONParameterEncoding;
return self;
}
- (void) uploadFiles:(NSArray*)files
path:(NSString*)path
parameters:(NSDictionary*)parameters
progressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block
success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure
{
NSMutableURLRequest *request =
[self multipartFormRequestWithMethod:@"POST"
path:path
parameters:parameters
constructingBodyWithBlock:
^(id <AFMultipartFormData>formData) {
for (CRLMultiPartFile *file in files) {
NSAssert(file.name, @"Name cannot be nil");
NSAssert(file.file, @"Nothing found to upload");
NSAssert(file.filename, @"FileName cannot be nil");
NSAssert(file.mimeType, @"Must set Mime-Type for %@", file.filename);
[formData appendPartWithFileData:file.file name:file.name fileName:file.filename mimeType:file.typeString];
}
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:block];
[operation setCompletionBlockWithSuccess:success failure:failure];
[self enqueueHTTPRequestOperation:operation];
}