声明委托协议

时间:2012-07-08 09:28:18

标签: iphone objective-c ios

我想知道在同一个类中声明protocol并在单独的文件中声明它时有什么区别;例如:

#import <UIKit/UIKit.h>

@class MyClassA;

@protocol MyDelegate <NSObject>

@required
- (MyClassA*)myMythod;

@optional
- (void)anOtherMethod:(NSString*)ID;

@end

@interface MyClassB : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, assign) id <MyDelegate> delegate;
......

这里我使用MyClassB在同一个文件中声明协议delagate,我可以在一个单独的源文件中声明它(协议委托)。在同一个文件中将它与类和单独的文件中声明它有什么区别?谢谢!

3 个答案:

答案 0 :(得分:8)

肯定有微妙的差异。

如果您正在谈论的协议是一个特定类使用的委托,例如MySpecialViewControllerMySpecialViewControllerDelegate,那么您可能非常喜欢保持两个声明在同一标题中。例如,如果另一个类要实现该协议,则可能在MySpecialViewController类上依赖逻辑。因此,您不会引入任何其他依赖项。

但是,使用协议还有另一个重要原因(至少)。您可能试图解耦两个类之间的双向依赖关系。当然,编译器不允许两个标头#import彼此。但是,即使您将一个班级的#import移到 .m 文件中,也常常表明设计不佳会让两个班级完全了解彼此的完整API。

一种解决这种关系的方法是让一个类只通过另一个实现的协议来了解另一个。也许Parent拥有并创建Child类,因此必须#import "Child.h"。但是,Child还需要在foo:bar:上调用Parent方法。你可以制作一个FooProtocol

@protocol FooProtocol
  - (void) foo: (int) arg1 bar: (BOOL) arg2;
@end

然后在Parent.h中:

@interface Parent : SomeBaseClass<FooProtocol> {
}

允许Child执行此操作:

@interface Child {
}
@property (assign) id<FooProtocol> fooHandler;

并使用它

[fooHandler foo: 1 bar: YES];

这使得孩子不直接依赖Parent类(或Parent.h)。但是,只有在FooProtocol.h中保留FooProtocol的声明,而不是在Parent.h中,这才有效。同样,如果FooProtocol只使用了Child,那么将它保留在Child.h中,但是可能不会,如果此协议是由Child 以外的其他类使用。

因此,总而言之,如果您希望保留最大限度地分隔类之间的相互依赖关系,或者鼓励在设计中更好地分离,请将协议保留在单独的标题中。

答案 1 :(得分:1)

没有区别。这只是你喜欢整理标题的问题。

例如,我喜欢在一个文件中保留与“一个功能实体”(无论这意味着什么,定义不同:-))相关的所有内容。因此,使用实现协议的委托的类将在同一标头中声明类和协议,因为它们几乎只是同一建筑物的不同砖块。

答案 2 :(得分:0)

将单独的头文件中的协议与类的头文件之间的唯一区别是它允许将协议包含为可选的,这可以帮助解决任何命名冲突,但前缀应该是协议解决方案。

惯例似乎是将相关协议包含在类的头文件中,因为它更有条理并且保持在一起,但是如果你有非常大的协议,它可能更有意义。它们位于单独的文件中,以使您的类标题更易于阅读。