委托单个对象

时间:2012-02-28 02:18:59

标签: objective-c ios cocoa-touch

我有一个NSObject,它是一个单身人士。有没有为这个单身人士课程设立代表的问题?我担心单身人士会失败。

这是我的情景。我有一个函数(在这个单例类中),它执行异步请求以从API中提取NSDictionary。基本上,当这个请求完成时,我想通知一个类请求已经完成。

3 个答案:

答案 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];
        } 
    }];
}

我在许多应用中成功使用了多委托模式。如果选择这种方法,请注意多线程如何影响事物。

相关问题