标题本身就足以解决我的问题了。但是我会在这里进一步解释,考虑我有一个两个视图控制器A和B. A是基础并且它正在推动B,在一种情况下,我希望在视图(B)中单击一个按钮时从B中暗示A。如果我有那个实例,Objective C允许直接调用一个视图。我认为这样做不是一个好习惯。应该如何处理这个案子..
感谢您的建议。
答案 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
中的“使用弱参考以避免保留周期”