在iOS 7中,在视图控制器之间传递数据

4

我正在开发一个应用程序,需要在视图控制器之间传递数据。我知道这是一个常见的问题,但我找不到我的问题的答案:我能够从第一个视图控制器(MasterViewController 在我的情况下)向第二个视图控制器(SettingsViewController)传递数据,但不能反过来。我在SecondViewController.m文件中调用FirstViewController的方法,它可以记录数据。但是,当我退出SecondViewController时(使用[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];),数据被重置。

我尝试了其他方法来传递数据,但没有成功。我正在使用这段代码来传递数据:

MasterViewController *vc = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil];

[vc setPorts:SelectedPorts];

我也尝试将[vc setPorts:SelectedPorts];替换为vc.selectedCellIndexes = SelectedPorts;,但是出现了相同的问题。 setPorts方法在FirstViewController.h文件中声明,而SelectedPorts是我在SecondViewController.m中声明的变量(它不为nil,我已经检查过)。
以下是FirstViewController.m中的setPorts::
- (void) setPorts:(id)selectedPorts {
selectedCellIndexes = selectedPorts;
NSLog(@"selectedCellIndexes : %@", selectedCellIndexes);
}

这段代码记录了一个好的数值,但是当我在FirstViewController.m中的viewWillAppear方法中记录它时,它会被重置为在SecondViewController.m中调用该方法之前的数值。

只是为了澄清,如果我不退出SecondViewController.m,数据就不会被重置。

我已经阅读了您所有的评论,并且非常感谢您的帮助。为了方便起见,我使用了全局变量。

感谢您的帮助。


数据在 secondViewController 中被重置,它的 iVars 被释放。您需要在主视图控制器上创建一个 ivar,以始终保存您所说的数据。 - Woodstock
请问您能给我一些关于如何完成这个任务的建议吗? - jrock007
@jrock007,你能否展示一下你如何声明和实现委托协议? - Abizern
嗨,@jrock007,有7个人花时间写答案。你能否让我们保持更新? - Stéphane Bruckert
6个回答

1
在 secondViewController 中,您创建协议。
  #import <UIKit/UIKit.h>

@protocol sampleDelegate <NSObject>

- (void)passValue:(id)selectedPorts

@end

@interface SecondViewController : UIViewController

@property (nonatomic, strong) id <sampleDelegate> passDelegate;

@end

在viewDidLoad方法或其他需要的地方,调用以下方法:
[self.passDelegate passValue:selectedPorts];

在FirstViewController.h中,

导入代理<sampleDelegate>

#import "SecondViewController.h"

@interface FirstViewController : UIViewController<SampleDelegate>

@end

在FirstViewController.m文件中,
-(void)passValue:(id)selectedPorts
{
    id receivedValues = selectedPorts;
}

并在您的SecondViewController分配中设置自己。

SecondViewController *vc = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
vc.passDelegate = self;

需要在FirstViewController.m中分配吗?我需要将数据从SecondViewController传递到FirstViewController,而不是传递到SecondViewController。 - jrock007
你需要反转吗?将secondview翻转到Master视图? - karthika
在你的firstViewController中导入delegate,还有一个重要的是,在创建secondviewController之后,在分配之后放置delegate = self。我已经编辑了代码,请查看。 - karthika
我添加了以下代码(我得到@interface MasterViewController:UITableViewController <UISearchBarDelegate,UISearchDisplayDelegate,sampleDelegate>),但是出现了错误:“无法找到'sampleDelegate'协议声明”。我导入了SecondViewController(#import "SettingsViewController.h"),并在SettingsViewController.h中添加了以下代码:一个协议sampleDelegate <NSObject>
  • (void)passValue:(id)selectedPorts);
结束。
- jrock007
在 SecondViewController 中的接口声明之前声明协议。 - karthika
显示剩余14条评论

1
  • 您在MasterViewController中有一个端口列表,并希望在SettingsViewController中使用它。
  • MasterViewController可以保存此列表,SettingsViewController应该可以访问它。

SettingsViewController中,添加一个setSelectedPort方法:

@property (nonatomic, retain) id selectedPorts

- (void) setPorts:(id)selectedPorts;

该方法将所选端口列表保存到属性中。
MasterViewController中调用SettingsViewController并将列表传递给它。
SettingsViewController *vc = [[SettingsViewController alloc] initWithNibName:@"SettingsViewController" bundle:nil];
[vc setSelectedPorts:yourValue]; 

当在SettingsViewController内修改列表时,即使您离开SettingsViewControllerMasterViewController中包含的端口列表也不会移动。


问题在于用户输入了端口,所以我不能仅仅调用一个方法来更改它们。 - jrock007
如果您将列表实例(引用)保存到“SecondViewController”中,则可以对列表进行任何更改。只需将其保存为属性即可。答案已更新。 - Stéphane Bruckert

0

获取结果并没有什么异常。通过执行

MasterViewController *vc = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil];   
[vc setPorts:SelectedPorts];

你正在从你的SecondViewController创建一个新的MasterViewController实例。这不同于你导航到SecondViewController的方式。因此,你将无法获得预期的结果。因为你正在将端口([vc setPorts:SelectedPorts])设置为新创建的主控制器实例。

与其创建一个新实例,只需在SecondViewController中保留对MasterViewController的引用,并在移动到第二个VC之前分配它。作为初学者,我建议使用这种方式。但是使用委托是传递数据的首选方式。


0

要么使用委托方法从模态视图控制器与主视图控制器进行通信,或者如果您想从模态视图控制器中检索一些操作对象,则可以像这样做。

将对象设置为模态视图控制器的.h文件中的属性(以便它们是公共的)。

使用取消 unwind segue,在主视图控制器中只需执行此操作:

-(IBAction)exitModalVC:(UIStoryboardSegue*)segue
{
    SomeObject *obj = ((YourModalVC*)segue.sourceViewController).someObject;

    //Do what you want with obj
}

编辑:

这只适用于使用 unwind segue(在使用故事板时关闭模态 VC 的好方法)的情况下才能正常工作。

如果您没有使用 unwind segue,则无法使用此方法:

[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];

0
你在第二个视图控制器中创建了第一个视图控制器的一个新实例,而不是访问原始调用者的同一个实例。这就是为什么当你返回到原始调用者 - 你的MasterViewController时,虽然你可以看到日志,但数据却不在那里的原因。
你需要使用委托方法。查看我对此的答案SO.

0

这是与对象所有权相关的问题。 请按照以下步骤操作:

根据理解,您想要从“SecondViewController”向“FirstViewController”返回值。

不要在SecondViewController中创建FirstViewController的新对象,这样不起作用。

  1. 在“SecondViewController.h”文件中创建“FirstViewController”的对象。 @property (nonatomic,strong) FirstViewController *firstViewController;

  2. 当您从FirstViewController导航到SecondViewController时,请传递“self”。 例如:SecondViewController *vc = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; vc.firstViewController = self;

  3. 如果您想将反向值传递给FirstViewController,则在SecondViewController.m文件中。 [self.firstViewController setPorts:SelectedPorts];

  4. 并在FirstViewController.m中使用最新值刷新控件。

尝试以上代码,肯定能满足您的需求。


当我在SecondViewController.h中添加以下内容时,会出现错误:@property (nonatomic,strong) MasterViewController *masterViewController; 这些错误是:"unknown type name MasterViewController"和"property with 'retain (or strong)' attributes must be of object type." MasterViewController是我的FirstViewController的名称。 - jrock007
请在 SecondViewController 中导入相同的 (MasterViewController) 类。 #import "MasterViewController.h" - Amol
你正在创建MasterViewController对象,所以你需要导入同样的类。#import "MasterViewController.h" - Amol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接