2010-01-30 41 views
4

我为ObjC类创建了自己的委托。该类本身处理核心数据操作。委托方法用于通知其他类关于发生在数据存储上的变化。处理数据存储的类称为Datastore,它的委托称为DatastoreDelegate。我的UIViewController(ContactsViewController)实现了委托。作为跟随委托方法似乎是@required,它被声明为@optional

我DatastoreDelegate声明:

@class Datastore; 
@protocol DatastoreDelegate <NSObject>; 
@optional 
- (void)didAddMessage:(Message *)message; 
- (void)didUpdateContact:(Contact *)contact; 
- (void)didAddContact:(Contact *)contact; 
- (void)didUpdateContact:(Contact *)contact; 
- (void)didDeleteContacts; 
@end 

奇怪的是,我的代码都能正常运作这些方法除了[didAddMessage:]方法。每当我尝试从Datastore类中调用此委托时,我都会从ContactsViewController中获取一个错误。该错误告诉我在ContactsViewController实例(发送给实例的无法识别的选择器)中缺少[didAddMessage:]选择器。如果选择器是可选的,该如何丢失?

我应该注意到我的Datastore类是一个Singleton。我不确定这是否与我遇到的这个问题有关。

回答

23

“可选”意味着调用者是负责检查目标响应一个给定的选择。例如: -

if ([_myDelegate respondsToSelector:@selector(didAddMessage:)]) 
{ 
    [_myDelegate didAddMessage:theMessage]; 
} 
4

你实现你的ContactsViewControllerdidAddMessage:?它是可选的,所以你不必强制执行它,但是如果你发送didAddMessage:消息到ContactsViewController,但实际上没有在ContactsViewController中实现它,你仍然会得到一个编译器警告。换句话说,@optional意味着你不必实现它,但是如果你还没有实现它,但是尝试使用它,编译器仍然可能会发出警告。

什么你可能想在Datastore做的是这样的:

if ([delegate respondsToSelector:@selector(didAddMessage:)]) { 
    [delegate didAddMessage:theMessage]; 
} 

,而不仅仅是:

[delegate didAddMessage:theMessage]; 

(你还是会在第一时间拿到例如编译器警告,但它是安全的忽略,因为你在运行时检查,看是否合适的方法是在委托实现)

+0

感谢时,[respondsToSelector:]消息固定我的问题。当消息本身被声明为@optional时,需要这样的消息很奇怪。 – 2010-01-30 19:47:52

+0

想一想:如果该方法是可选的,那么委托类可能没有实现它。如果您发送委托人未回复的邮件,则会发生崩溃(默认情况下)。 – mipadi 2010-01-30 19:52:53

+0

@optional仅仅意味着一个说它满足协议的类并不需要实现该方法。令你感到困惑的事情 - 调用者检查[respondsToSelector:] - 是所有委托消息的工作方式。 – 2010-01-30 19:53:27