objective-c - 在 navigationController 堆栈上多级传递委托(delegate)方法

标签 objective-c ios delegates uinavigationcontroller

我在工具栏中有一个按钮,它有一个与之关联的弹出窗口。在弹出框内,我设置了一个导航 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/

相关文章:

iphone - 如何显示 CFStringType?喜欢 kABHomeLabel

iphone - UIViewController显示两个UITableView

ios - Core Data SIGABRT 什么时候取数据?

ios - 为具有闭包默认值的属性设置委托(delegate)

C#构造函数的方法引用

ios - 检测何时通过 App Delegate 的 UITabBarController 按下 tabBar 项目

ios - 遍历数组,索引错误

ios - 如何在ios 12中将本地视频嵌入到UIView中

ios - UILabel Swift-3中显示的额外行

c# - 在 .Net 解决方案中将委托(delegate)放在哪里