在构造函数中传递控制器总是一个坏习惯吗?

时间:2013-02-14 02:44:30

标签: cocoa uiviewcontroller delegates protocols

我偶尔会通过传入视图控制器实例本身从视图控制器中实例化一个类,以便我创建的对象可以调用控制器的方法来更新视图。

这总是,经常,或从来都不是一种坏习惯吗?

具体地:

ViewController.h有

-(void)updateButtonValue:(NSString*)value;

MyObject.h有

-(id)initWithViewController:(ViewController*)aViewController;

我用我的视图控制器实例化该类:

[[MyObject alloc] initWithViewController:self];

因此允许MyObject实例通过简单的调用来更新视图中的按钮值,如:

MyObject.m

[self.viewController updateButtonValue:@"example"];

它似乎并不理想,因为我传递给MyObject的次数(视图控制器本身)比它应该需要的多,但它肯定是快速且功能性的。如果有一种更清洁的方法,例如依赖协议,这也很简洁,那么我们将非常感谢一个简短的代码示例。

1 个答案:

答案 0 :(得分:4)

传入一个类类型的指针总是不好的做法,因为你将对象紧密耦合在一起(每个对象需要知道另一个对象的类,它们也可能是一个单独的对象)。这就是委托模式的用途。它最小化了MyObject需要的信息(最低限度,只不过是指针类型id - 最好是MyObject指定的协议,为它提供一些行为保证)

所以翻译你的例子

MyObject.h

取代...

-(id)initWithViewController:(ViewController*)aViewController;

与......

-(id) init; 

(如果您没有其他理由可以覆盖,可以省略)

和...

@property (nonatomic, weak) id delegate;

myViewController中的实例化(需要#include MyObject)...

MyObject* object = [[MyObject alloc] init];

其次是

object.delegate = self;

(注意object获取指向myViewController的指针,而无需了解其他任何内容)

现在您可以在object内部执行此操作:

 [self.delegate updateButtonValue:@"example"];

但是 ...您需要确保您的代理人能够收到updateButtonValue消息:

要执行此操作,请在MyObject.h中使用此方法的签名声明协议

@protocol MyObjectDelegate

  - (void) updateButtonValue:(NSString*)string;

@end

在viewController中,使用<>声明您符合此协议在接口行

@interface ViewController <MyObjectDelegate>

(这没什么大不了的,ViewController已经有#include MyObject来分配/初始化它,所以不需要更多的信息来做这件事了)

并扩展您的财产声明:

@property (nonatomic, weak) id <MyObjectDelegate> delegate

现在,您已为编译器提供了足够的信息,以确保您只能传递符合条件的消息。这里的好处是,MyObject可以放心地将消息传递给MyViewController,而不需要知道关于MyViewController的任何,而不是通过委托指针到达它。