将委托方法多级传递给 navigationController 堆栈

Posted

技术标签:

【中文标题】将委托方法多级传递给 navigationController 堆栈【英文标题】:Pass a delegate method multi-levels up a navigationController stack 【发布时间】:2011-08-29 13:45:52 【问题描述】:

我在工具栏中有一个按钮,它有一个与之关联的弹出框。在弹出框内,我设置了一个导航控制器。我想要实现的是在导航控制器堆栈中向下两到三层的视图控制器来更改最初称为弹出框的按钮的状态。我已经设法做到了,但它需要几个代表,而且看起来很笨重;我在这里发帖的原因是想知道是否有更优雅、更有效的解决方案。

所以,开始吧:

//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 的委托设置为 MainController ,然后使用两个视图控制器的 NSArray 来设置导航控制器堆栈,但它确实弄乱了视图控制器出现在导航控制器中的方式:我即使在 navcontroller 的 rootviewcontroller 上也会有一个后退按钮,您可以继续单击 Back 并在 navcontroller 堆栈中转来转去,而不是在根目录处停止。有什么更好的方法来做到这一点吗?

【问题讨论】:

【参考方案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.

【讨论】:

谢谢,那会很好用。我曾考虑在这种情况下使用 NC,但我对它们并不熟悉。我会探索这个选项。 @Chris - 关于通知的唯一棘手部分是通知中心不保留或释放观察者。所以你必须记住在释放它们时移除任何观察者,否则有可能将消息发送到死实例。

以上是关于将委托方法多级传递给 navigationController 堆栈的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 DependencyService 和接口委托将 xamarin.android 特定功能的方法传递给 xamarin.forms?

将异步委托传递给Task.Run? [复制]

将摇动手势事件传递给应用程序委托

Alamofire/Swiftyjson - 将 JSON 类型传递给 Objc 协议委托

如何将变量传递给 UIAlertView 委托?

Flutter StatefulWidget传递数据,多级控件传递数据