我发现自己在代码中使用AFHTTPRequestOperationManager
重复了很多代码,所以我在考虑对它进行子类化,所以我可以将它设置为单例,并将所有代码放在子类中,如反对通过我的项目展开它。然而,在AFNetworking 2.0(http://nshipster.com/afnetworking-2/)的NSHipster剧集中,它说:
2.0中的主要区别在于您实际上是直接使用此类,而不是将其子类化,原因如“序列化”部分所述。
由于AFNetworking和NSHipster拥有相同的作者,我认为这是一个有效的论点。
所以我的问题是,为了在一个类中使用大多数网络代码,人们是否将AFHTTPRequestOperationManager
子类化,或者我是否忽略了使用框架的某些内容?
答案 0 :(得分:1)
这就是我解决它的方法。
我创建了一个新的MyDBClient对象,AFHTTPRequestOperationManager
是一个属性。 MyDBClient是一个单例类。然后我从我的视图控制器调用我的MyDBClient,然后设置操作管理器并启动请求。这样做的好处是更容易在AFHTTPRequestOperationManager
(iOS7之前)和AFHTTPPSessionManager
(iOS7)之间切换。
答案 1 :(得分:1)
我有一个连接类的对象。这会向任何对象广播不同的通知,可以通过[NSNotificationCenter defaultCenter]
注册。
-(void) requestData
{
[[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingStarted object:nil];
[_sessionManager setDataTaskDidReceiveDataBlock:^(NSURLSession *session,
NSURLSessionDataTask *dataTask,
NSData *data)
{
if (dataTask.countOfBytesExpectedToReceive == NSURLSessionTransferSizeUnknown)
return;
NSUInteger code = [(NSHTTPURLResponse *)dataTask.response statusCode];
if (!(code> 199 && code < 400))
return;
long long bytesReceived = [dataTask countOfBytesReceived];
long long bytesTotal = [dataTask countOfBytesExpectedToReceive];
NSDictionary *progress = @{@"bytesReceived": @(bytesReceived),
@"bytesTotal": @(bytesTotal)};
[[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceProgress object:nil userInfo:progress];
}];
[self.sessionManager GET:@"recipient/"
parameters:nil
success:^(NSURLSessionDataTask *task, id responseObject)
{
[[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingSucceeded
object:nil
userInfo:@{@"response": responseObject}];
}
failure:^(NSURLSessionDataTask *task, NSError *error)
{
NSUInteger code = [(NSHTTPURLResponse *)task.response statusCode];
NSString *msg;
switch (code) {
case kCuriculumDataSourceFetchErrorAPIKeyNotFound: msg = @"Api Key not found or revoked"; break;
case kCuriculumDataSourceFetchErrorServerDown: msg = @"Server Down"; break;
default: msg = [error localizedDescription]; break;
}
[[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingFailed
object:nil
userInfo:@{@"error": msg}];
}];
}
将收到的数据写入核心数据的对象将注册kCuriculumDataSourceFetchingSucceeded
,并可通过notification.userInfo[@"response"]
访问收到的回复。
ViewController将注册kCuriculumDataSourceFetchingSucceeded
,kCuriculumDataSourceFetchingFailed
和kCuriculumDataSourceProgress
。
我只实例化一个对象,如果它是单例,我不必费心。因此,我不必对它进行子类化或做一些相关的对象技巧来获得一个返回单例对象的方法。对从网络获取的数据感兴趣的类只会监听通知 - 他们不必知道获取数据的对象,也不必知道它是否是唯一的类型。
连接类对象本身可以注册到其他类将发布的通知,以触发新的数据提取。
视图控制器可以注册
等通知-(void)configure
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingStarted:) name:kCuriculumDataSourceFetchingStarted object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingSucceeded:) name:kCuriculumDataSourceFetchingSucceeded object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingFailed:) name:kCuriculumDataSourceFetchingFailed object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataSourceProgress:) name:kCuriculumDataSourceProgress object:nil];
}
在这种情况下,视图控制器和网络控制器导入相同的配置头文件,该文件定义了kCuriculumDataSourceFetchingSucceeded
等标记。但由于这些都是普通的NSStrings,因此即使是这种依赖也可以轻松避免。
将处理通知的视图控制器方法的示例
-(void)dataSourceProgress:(NSNotification *)notification
{
float bytesReceived = (float)[notification.userInfo[@"bytesReceived"] longLongValue];
float bytesTotal = (float)[notification.userInfo[@"bytesTotal"] longLongValue];
float progress = bytesReceived / bytesTotal;
dispatch_async(dispatch_get_main_queue(), ^{
self.progressView.progress = progress;
self.imgView.layer.mask = self.progressView.layer;
});
}