11

我遇到了一个有趣的问题,我有主 ViewController,让我们用导航控制器称他为 MainVC,我正在从他执行 performSegueWithIdentifier 到我的第二个 ViewController,让我们称他为 SecVC。因此,当我尝试执行 popViewControllerAnimated 时,我想将一些数据从 SecVC 传递到 MainVc .. 我知道我可以使用 appDelegate Param 或单例类来做到这一点,但我的问题是:我可以用更优雅的解决方案来做到这一点吗?就像我使用 prepareForSegue 并使用本地参数..

谢谢...

4

5 回答 5

18

最好的方法是使用委托。

//SecVCDelegate.h

#import <Foundation/Foundation.h>

@protocol SecVSDelegate <NSObject>

@optional
- (void)secVCDidDismisWithData:(NSObject*)data;
@end

//SecVC.h

#import <UIKit/UIKit.h>
#import "SecVSDelegate.h"

@interface SecVC : UIViewController

/** Returns the delegate */
@property (nonatomic, assign)   id<SecVSDelegate> delegate;

@end

//SecVC.M

...

- (void) dealloc
{
...
delegate = nil
...
}

每当你 popViewControllerAnimated,在它之后(或之前)你这样做

if(_delegate && [_delegate respondsToSelector:@selector(secVCDidDismisWithData:)])
{
[_delegate secVCDidDismisWithData:myDataObject];
}

在 MainVC 中你必须确定你实现了委托函数 //MainVC.m

- (void)secVCDidDismisWithData
{
//do whatever you want with the data
}

为避免任何警告,您必须告诉 MainVC 类实现委托,如下所示:

//MainVC.h

#import "SecVCDelegate.h"
...
@interface MainVC : UIViewController <SecVCDelegate>
...
secVCInstance.delegate = self;
[self.navigationController pushViewController:secVCInstance]; 
...
于 2012-11-22T10:01:46.320 回答
16

虽然我同意最好的选择是使用Delegate,但如果有人正在寻找不同的东西,他可以使用NSNotificationCenter作为替代方案。

在MainVC 的viewDidLoad中:

- (void)viewDidLoad
{

    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(recvData:)
                                             name:@"SecVCPopped"
                                           object:nil];
}

并在 MainVC.m 中添加方法recvData

- (void) recvData:(NSNotification *) notification
{

    NSDictionary* userInfo = notification.userInfo;
    int messageTotal = [[userInfo objectForKey:@"total"] intValue];
    NSLog (@"Successfully received data from notification! %i", messageTotal);
}

现在在 SecVC 中,在弹出之前,添加这一行

NSMutableDictionary* userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:[NSNumber numberWithInt:messageTotal] forKey:@"total"];

NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"SecVCPopped" object:self userInfo:userInfo];
于 2013-12-06T13:27:26.310 回答
1

我会通过以下方式之一来做,但我不确定它是否足够优雅......

  1. 在 SecVC 中,在调用之前添加一个@property MainVC *mainVC;Use[self.mainVC setSomeValue:...];[self.navigationController popViewControllerAnimated:...];

  2. 使用 [self.navigationController viewControllers]; 找出, 并在弹出的代码行之前MainVC *mainVC调用.[mainVC setSomeValue:...];ViewController

这是你想要的吗?

于 2012-11-22T09:55:31.197 回答
1

我只是在被关闭的视图中设置了一个协议(Swift 中的示例):

 protocol ExampleTableViewControllerDismissDelegate {
    func didDismiss(withData: Any)
}

var delegate: SearchableTableViewControllerDismissDelegate?

然后,当您像这样关闭/弹出视图时,您可以调用它

self.navigationController?.popViewController(animated: true)
delegate?.didDismiss(withData: Any)

然后在被解除的视图(层次结构中的父级)中,我们可以符合委托,并在视图被解除后基本上获得带有数据的回调。

//MARK: ExampleTableViewControllerDismissDelegate

func didDismiss(withData: Any) {
    //do some funky stuff
}

并且不要忘记使用订阅父视图中的委托

viewController.delegate = self
于 2017-03-01T16:57:20.890 回答
0

还有另一种在视图之间传递数据的方法,包括popViewControllerAnimated并且它使用全局 var 实例,因此如果您在详细视图中修改该 Var 并在执行popViewControllerAnimated之后,您可以在 viewWillAppear 方法中调用新数据。

第一步是在 main.h 中声明 Global var

NSMutableArray * layerList;

现在您必须在详细视图中调用它。

第二视图.m

extern NSString *layerList;

第二视图.h

-(void)back{
    layerList = @"Value to send";
    [self.navigationController popViewControllerAnimated:YES];
}

现在您可以在检测到弹出操作后使用主视图中的信息。

第一视图.m

extern NSString *layerList;

第一视图.h

-(void)viewWillAppear:(BOOL)animated{
   NSLog(@"This is what I received: %@",layerList);
}
于 2014-09-17T04:19:44.740 回答