如何避免在Objective C中循环调用?

时间:2013-01-17 09:28:27

标签: iphone ios objective-c cocoa-touch cyclic-reference

标题本身就足以解决我的问题了。但是我会在这里进一步解释,考虑我有一个两个视图控制器A和B. A是基础并且它正在推动B,在一种情况下,我希望在视图(B)中单击一个按钮时从B中暗示A。如果我有那个实例,Objective C允许直接调用一个视图。我认为这样做不是一个好习惯。应该如何处理这个案子..

感谢您的建议。

1 个答案:

答案 0 :(得分:2)

如果'A暗示B'你的意思是你想要调用最初负责推B的A,你只需使用'后退'按钮或代码返回A:

[self.navigationController popViewController animated:YES];

B不需要指向A的指针,导航控制器具有指针,并且B具有指向导航控制器的指针,因为导航控制器在创建B时设置B的navigationController属性。

如果您需要根据B中的某些操作在A中设置属性,则应使用委托来执行此操作。

在B中,您创建了一个名为delegate的属性。

在A中,当您创建B时,将其委托设置为A:

ViewControllerB* vcB = [[ViewControllerB alloc] init];
vcB.delegate = self;
[self.navigationController pushViewController:vcB];

然后在B中你可以在pop之前通过委托回叫A:

[self.delegate sendMessageWithValue:someValue];
[self.navigationController popViewController animated:YES];

如果您想要格外小心,可以使用以下内容附上留言:

if ([self.delegate respondsToSelector:@selector(sendMessageWithValue:)]) { ... }

为了在没有B知道任何关于A的情况下完成这项工作,除了它是委托之外,B应该在标题中声明一个委托协议(@interface之上)

@protocol BDelegateProtocol
- (void) sendMessageWithValue:(int)someValue;
@end

当您在B delegate中声明@interface属性时,请指定预期遵循的协议:

@property (nonatomic, weak) id <BDelegateProtocol> delegate;

在A的@interface标题中,宣传您遵循该协议:

#import BViewController;

@interface AViewController:UIViewController <BDelegateProtocol>

这是你所追求的松耦合。 B不必导入A的标题。除了它符合B的协议规范之外,它不需要了解A。

B确实持有指向A的指针,但它是指针。这是非常重要的。如果委托属性是 strong ,则B会将其委托的保留计数增加1.如果委托拥有指向B的强指针,那么它们都不能得到解除分配。当A存在时,B将始终具有至少1的保留计数,同样A在B存在时将始终具有保留计数1:两者都不能被销毁。

在这种可能不会发生的特殊情况下 - A不需要保留B,因为它是Nav Controller所做的 - 但是这种情况经常会出现,因为委托通常是创建和拥有委托者的对象。请参阅Apple的Practical Memory Management

中的“使用弱参考以避免保留周期”