我在工具栏中有一个按钮,它有一个与之关联的弹出窗口。在popover中,我已经设置了一个navigationcontroller。我想要实现的是导航控制器堆栈中的两个或三个级别的视图控制器,以更改最初调用弹出窗口的按钮的状态。我设法做到了这一点,但它需要几个代表,看起来非常笨重;我在这里发帖的原因是要弄清楚是否有更优雅和有效的解决方案。
所以,开始吧:
//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,我的navController的rootViewController:
//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-ish方式。我尝试在MainController中初始化A_Controller和B_Controller并在那里将B_Controller的委托设置为MainController,然后使用两个viewcontrollers的NSArray来设置navcontroller堆栈,但它确实搞砸了viewcontrollers出现在navcontroller中的方式:I即使在navcontroller的rootviewcontroller上也会得到一个后退按钮,你可以继续单击Back并绕过navcontroller堆栈而不是停在根目录。有关更好方法的任何想法吗?
答案 0 :(得分:1)
如果您想要分离视图控制器,您可以定义一个通知,然后发布该通知。
这样,只有接收通知的根视图控制器才需要知道深层嵌套视图控制器。
像这样定义通知:
// In .h
extern NSString* const BlaControllerDidUpdateNotification;
// In .m
NSString* const BlaControllerDidUpdateNotification = @"BlaControllerDidUpdateNotification";
深度嵌套的控制器(BlaController
)需要发布如下消息:
[[NSNotificationCenter defaultCenter]
postNotificationName:BlaControllerDidUpdateNotification
object:self];
根视图控制器需要对此进行操作:
// 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.
}