我在工具栏中有一个按钮,它有一个与之关联的弹出窗口。在弹出框内,我设置了一个导航 Controller 。我想要实现的是在导航 Controller 堆栈中向下两层或三层的 View Controller 来更改最初称为弹出窗口的按钮的状态。我已经设法做到了,但它需要几个委托(delegate),而且看起来很笨重;我在这里发帖的原因是想弄清楚是否有更优雅、更高效的解决方案。
所以,开始吧:
//ProtocolDeclaration.h
@protocol ADelegate <NSObject>
- (void)changeButtonState;
@end
@protocol BDelegate <NSObject>
- (void)passTheBuckUpTheNavChain;
@end
然后,对于我的包含按钮的 MainController:
// MainController.h
#import "A_TableController.h"
#import "ProtocolDeclaration.h"
@class A_TableController;
@interface MainController : UIViewController <ADelegate>
...
@end
// MainController.m
- (IBAction)buttonPressed:(id)sender {
A_Controller *ac = [[[A_Controller alloc] init] autorelease];
ac.ADelegate = self;
UINavigationController *nc = [[[UINavigationController alloc] initWithRootViewController:ac] autorelease];
UIPopoverController *pc = [[[UIPopoverController alloc] initWithContentViewController:nc] autorelease];
[pc presentPopoverFromBarButtonItem...]
}
// ADelegate Method in MainController.m
- (void)changeButtonState
{
self.button.style = ....
}
现在,对于 A_Controller,我的 rootViewController 用于我的 navController:
//A_Controller.h
#import "B_Controller.h"
#import "ProtocolDeclaration.h"
@class B_Controller;
@interface A_Controller : UITableViewController <BDelegate>
{
id<ADelegate> delegate;
...
}
@property (assign) id<ADelegate> delegate;
...
@end
//A_Controller.m
//In the method that pushes B_Controller onto the stack:
B_Controller *bc = [[[B_Controller alloc] init] autorelease];
bc.BDelegate = self;
[self.navigationController pushViewController:bc animated:YES];
//In the BDelegate Method in A_Controller:
- (void)passTheBuckUpTheNavChain
{
[ADelegate changeButtonState];
}
最后,在 B_Controller 中:
//B_Controller.h
#import "ProtocolDeclaration.h"
@interface A_Controller : UITableViewController
{
id<BDelegate> delegate;
...
}
@property (assign) id<BDelegate> delegate;
...
@end
//B_Controller.m
//Where it's necessary to change the button state back up in MainController:
[BDelegate passTheBuckUpTheNavChain];
现在,这行得通了,但它似乎有点像 Rube-Goldberg 式的做法。我尝试在 MainController 中同时初始化 A_Controller 和 B_Controller,并将 B_Controller 的委托(delegate)设置到 MainController,然后使用两个 View Controller 的 NSArray 来设置导航 Controller 堆栈,但这确实搞砸了 View Controller 在导航 Controller 中的显示方式:我即使在 navcontroller 的 rootviewcontroller 上也会有一个后退按钮,您可以继续单击“后退”并在 navcontroller 堆栈上来回走动,而不是停在根部。关于更好的方法有什么想法吗?
最佳答案
如果你想解耦 View Controller ,你可以定义一个通知,然后发布那个通知。
这样只有接收通知的 Root View Controller 需要知道深层嵌套的 View Controller 。
像这样定义通知:
// In .h
extern NSString* const BlaControllerDidUpdateNotification;
// In .m
NSString* const BlaControllerDidUpdateNotification = @"BlaControllerDidUpdateNotification";
深度嵌套的 Controller (BlaController
)需要像这样发布消息:
[[NSNotificationCenter defaultCenter]
postNotificationName:BlaControllerDidUpdateNotification
object:self];
Root View Controller 需要像这样对它进行操作:
// In init or the like:
[[NSNotificationCenter defaultCender]
addObserver:self
selector:@selector(blaControllerDidUpdateNotification:)
name:BlaControllerDidUpdateNotification
object:nil];
// And then define this method:
-(void)blaControllerDidUpdateNotification:(NSNotification*)notification {
// Update UI or whatever here.
}
关于objective-c - 在 navigationController 堆栈上多级传递委托(delegate)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7230985/