我有一个NSObject,它是一个单身人士。有没有为这个单身人士课程设立代表的问题?我担心单身人士会失败。
这是我的情景。我有一个函数(在这个单例类中),它执行异步请求以从API中提取NSDictionary。基本上,当这个请求完成时,我想通知一个类请求已经完成。
答案 0 :(得分:31)
不,代表不会失败,但请考虑改为使用NSNotificationCenter:
static NSString *const kMyClassNotificationName = @"myClassNotificationName";
// where you would call a delegate method (e.g. [self.delegate doSomething])
[[NSNotificationCenter defaultCenter] postNotificationName:kMyClassNotificationName object:self userInfo: /* dictionary containing variables to pass to the delegate */];
// where you would set up a delegate (e.g. [Singleton instance].delegate = self)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething) name:kMyClassNotificationName object:[Singleton instance]];
答案 1 :(得分:19)
您基本上有三种选择:
使用代理人。一个singelton是一个对象,所以它可以有一个代表。如果有几个对象需要使用它并且需要将自己设置为委托,那么每次都可以重置它们,但这可能会变得毛茸茸。
使用通知,如Richard J. Ross III所示,但严肃地说:对我来说似乎很奇怪,如果你有一个单身人士,需要通知一位代表,但你要使用广播技术
使用完成块,其中调用对象将块传递给单例,一旦单例完成任务,就会执行该块。请参阅[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]
(好吧,这不是单例,而是类方法。原理是相同的),它使用一个完成块,或者使用成功和失败块的伟大AFNetworking 。
从它的示例代码:
[[AFGowallaAPIClient sharedClient] getPath:urlString
parameters:mutableParameters
success:^(__unused AFHTTPRequestOperation
*operation,
id JSON)
{
NSMutableArray *mutableRecords = [NSMutableArray array];
for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) {
Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease];
[mutableRecords addObject:spot];
}
if (block) {
block([NSArray arrayWithArray:mutableRecords]);
}
} failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) {
if (block) {
block([NSArray array]);
}
}];
答案 2 :(得分:7)
为单例设置委托没有任何问题,但它确实会创建许多需要处理的边缘情况。如:
如果对象A调用setDelegate:,紧接着是对象B调用setDelegate:那么对象A永远不会接收委托调用。
在取消设置单身人士代表之前,您需要检查自己是否是代表。通常在dealloc
中,您拨打singleton.delegate = nil;
。如果你做了另一个对象碰巧成为委托,那么你刚刚导致他们意外地停止了委托。
与代表的单身人士并不是一个完善的模式。您的解决方案应根据您的用例的强大程度而有所不同。以下是一些解决方案(按最简单的顺序 - >最稳健)。
保持简单
将您的应用设计为永远不会让多个对象同时成为单身人士的代表(这可能是不可能的)。
<强> NSNotification 强>
使用NSNotificationCenter发出事件而不是委派信号。请参阅此主题中发布的其他一些答案。
多个代表
扩展您的单例以支持多个委托。将setDelegate:
替换为:addDelegate:
和removeDelegate:
@property (atomic) NSMutableArray *delegates;
- (void)addDelegate:(NSObject * <YourProtocol>)foo {
[self.delegates addObject:foo];
}
- (void)removeDelegate:(NSObject * <YourProtocol>)foo {
[self.delegates removeObject:foo];
}
- (void)signalDelegateEvent {
[self.delegates enumerateObjectsUsingBlock:^(id<YourProtocol> obj,
NSUInteger idx,
BOOL *stop) {
// call delegate method `foo` on each delegate
if ( [obj respondsToSelector:@selector(foo)]) {
[obj foo];
}
}];
}
我在许多应用中成功使用了多委托模式。如果选择这种方法,请注意多线程如何影响事物。