将对象返回到根视图控制器

时间:2011-12-22 03:26:56

标签: iphone objective-c ios uiviewcontroller

我知道很多地方已经涵盖了这个主题,但是在经历不同的答案时,我找不到适合我的情况的解决方案。

基本上我想做的事情很简单。我有一个带有表视图的视图控制器,以及一个+按钮,用于触发第二个视图控制器,用户可以在其中输入一个名称,然后将该名称添加到第一个视图控制器表视图中。想想iPhone上的联系人,您可以在其中添加新人(或亚马逊,您可以添加新的信用卡)。

我的问题是 - 将此字符串(在本例中)返回到表所在的视图控制器的最佳方法是什么?

人们建议使用NSDefaults,Delegate或singleton,这些对于这种情况都不是很好(每个都是出于自己的原因)。我真的只需要返回一个简单的字符串。

感谢您的帮助。

5 个答案:

答案 0 :(得分:4)

如果您从View Controller A导航--->查看控制器B,这是你的情况,然后你想传递来自B - >的信息。 A,建议使用松耦合,如委托。你讨论过几件事,比如NSUserDefaults,singleton,NSNotification,可能还有更多。

但代表团是更好,更标准的做法。

答案 1 :(得分:1)

您不会将新内容返回到TableView。您需要的是更新为您的tableView提供信息的来源 所以数据存在的地方是你需要去添加的地方,当你回到UITableViewController时,你可能需要告诉UITableView reload它的数据。

如果您绝对需要与它进行通信,则每个UIViewController都有一个句柄。

UIViewController *parentVC = aViewController.parentViewController;

答案 2 :(得分:1)

假设需要更新的ViewController是应用程序的根视图控制器,您可以执行以下操作:

  

YourViewController * yvc = [(YourAppDelegate *)[[UIApplication sharedApplication] delegate] viewController];

     

[yvc updateString:@“Updated String”];

请记住:

#import "YourAppDelegate.h"

但老实说,我会使用委托模式或NSNotification。

答案 3 :(得分:1)

三个不错的选择:

1)让第一个视图控制器将自身传递给第二个视图控制器,以便第二个控制器可以向第一个视图控制器发送消息。理想情况下,创建第一个控制器采用的协议,以便第二个控制器不依赖于第一个控制器的类型,只关心它实现协议:

@protocol Nameable
@property(copy) NSString* name;
@end;

@interface FirstViewController <Nameable>
//...
@end

@implementation FirstViewController
@synthesize name;
//...
@end

然后第一个控制器可以这样做:

SecondViewController *second = [[SecondViewController alloc]
initWithNibName:nil]; second.thingToName = self;
[self.navigationController pushViewController:second animated:YES];

到时候,第二个控制器可以做到这一点:

self.thingToName.name = nameString;

细节并不那么重要 - 这里要知道的主要事情是,如果要向对象发送消息,首先需要指向对象的指针。当第一个视图控制器设置second.thingToName = self时,它提供该指针。

2)让第一个视图控制器创建一个数据对象,其中第二个视图控制器可以存储数据,如下所示:

@interface Person <Nameable>
//...
@end

@implementation Person
@synthesize name;
//...
@end

现在第一个视图控制器可以创建一个新Person并传递:

SecondViewController *second = [[SecondViewController alloc]

Person *person = [[Person alloc] init];
[self.people addObject:person];
initWithNibName:nil]; second.thingToName = person;
[person release];

[self.navigationController pushViewController:second animated:YES];

这与第一种方法类似,只是接收名称的东西不是这里的视图控制器,它是某种数据容器(Person)。

您也可以在这里看到协议的值 - 请注意,第一个和第二个方法之间的SecondViewController类根本不会发生变化。它不是 care 它是否与视图控制器或Person的实例或其他任何东西交谈......只要该东西实现了Nameable协议,它就很高兴。

3)颠倒通信方向。不要让第二个视图控制器发送字符串,而让其父获取字符串。这可能是最简单的解决方案,尽管它确实需要父母知道孩子已经完成的方法。它会是这样的:

@implementation FirstViewController
//...

- (IBAction)addNewName:(id)sender
{
    self.secondController = [[SecondViewController alloc] initWithNibName:nil bundle:nil];
    [self.navigationController pushViewController:self.secondController animated:YES];
}

- (void)viewWillAppear
{
    if (self.secondController != nil) { // we must be returning from the child
        self.name = self.secondController.name;
        self.secondController = nil;
    }
}
@end

答案 4 :(得分:1)

这是你需要做的事情(请注意我在我的头顶输入这个,所以编译器可能在我的语法上有一些问题。)

在子视图控制器界面中:

@protocol ChildDelegate <NSObject>
- (void)didConfirmName:(NSString*)name
@end

@interface ChildViewController : UIViewController
...

@property (nonatomic, assign) id<ChildDelegate> delegate;

实现,在用户确认需要确认的内容时调用的方法内部:

- (void)myCustoMethod
{
    ...
    if ([self.delegate respondsToSelector:@selector(didConfirmName:)])
        [self.delegate didConfirmName:NAME_STRING];
}

在父视图控制器中,当您实例化子视图控制器时,将SELF指定为委托:

ChildViewController *vc = [[ChildViewController alloc] init...];
vc.delegate = self;

并实施:

- (void)didConfirmName:(NSString*)name
{
    // Do whatever you want with the name here...
}

还要确保告诉编译器您正在实施协议:

@interface ParentViewController () <ChildDelegate>
@end