我有一个连接类的对象。这会向任何可以通过[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}];
}];
}
将接收到的数据写入 Core Data 的对象将注册 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 之类的令牌。但由于这些是普通的 NSString,即使是这种依赖也可以轻松避免。
处理通知的视图控制器方法示例
-(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;
});
}