2011-12-22 134 views
1

我知道这个话题已经在很多地方被覆盖了,但是当经历不同的答案时,我找不到适合我的情况的解决方案。返回一个对象返回到根视图控制器

基本上什么,我试图做的是非常简单的。我有一个带有表格视图的视图控制器,还有一个+按钮,用于触发第二个视图控制器,用户可以在其中输入名称,然后将该名称添加到第一个视图控制器表格视图中。考虑iPhone上的联系人,你可以添加一个新的人(或亚马逊,你可以添加一个新的信用卡)。

我的问题是 - 什么是返回此字符串(在这种情况下)回视图控制器所在的表是最好的方式?

人们使用NSDefaults,委托或单身其中没有一个是针对这种情况(每一个为自己的原因),真的好建议。我真的只需要返回一个简单的字符串。

谢谢你的帮助。

回答

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 
+0

*这是唯一“正确”的方式*这是不正确的。有许多有效的方法可以在对象之间共享数据;代表团远不是唯一“正确”的方式。 – Caleb 2011-12-22 05:05:24

+0

够公平的,我会编辑我的答案,删除,因为你是对的。 – Rog 2011-12-22 05:14:12

1

你不回新事物的TableView中。你需要的是更新为你的tableView提供信息的来源。
因此,在数据存活的地方,你需要去添加它,当你回到UITableViewController时,你可能需要告诉UITableView它的数据是reload

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

UIViewController *parentVC = aViewController.parentViewController; 
+0

可以请你提供一个示例代码?我不清楚我是如何做到这一点的。为了简单起见,我们假设在根视图中没有表视图,只是需要更新的简单字符串。 – TommyG 2011-12-22 03:38:59

+0

试图,它不起作用。看起来我需要做一些铸造(见http://stackoverflow.com/questions/956990/accessing-parent-view-controller-custom-properties),这是不能被足够的方式,因为我不能似乎能够将字符串“写入”回父VC。 – TommyG 2011-12-22 03:55:35

+0

只是要留意,如果你使用的是导航控制器,该'parentViewController'返回将实际导航控制器,而不是以前的视图控制器。你应该在这个例子中使用委托,这是最简单也是最正确的。 – Rog 2011-12-22 04:36:04

4

如果从视图控制器A --->视图控制器B,在这里是你的情况下航行,然后你要传递的B信息 - > A,则建议使用松耦合,像代表团一样。你讨论过的东西有几个,比如NSUserDefaults,singleton,NSNotification,可能还有更多。

但代表团是更好的和标准的方法来做到这一点。

1

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

YourViewController * YVC = [(YourAppDelegate *)[[UIApplication的sharedApplication]委托]的viewController];

[YVC updateString:@ “字符的更新字符串”];

记住:

#import "YourAppDelegate.h" 

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

+0

这是不正确时,'viewController'方法/属性甚至不存在用于''。 – Rog 2011-12-22 04:39:00

+1

当然,它不会退出,但通常在应用程序委托你存储到您的应用程序的RootViewController的一个参考,你可以把它的viewController或任何你想要的...... – Ecarrion 2011-12-22 04:42:41

+0

问题是很多时候根视图控制器是一个导航控制器,标签栏控制器等 – Rog 2011-12-22 04:51:50

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]; 

而且在时机成熟时,第二控制器可以这样做:

​​

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

2)具有与第一视图控制器创建数据对象其中第二视图控制器可以存储数据,例如:

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

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

现在第一视图控制器可以创建新的人与通即:

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]; 

这类似于第一种方法,只收到所述名字的东西是不是在这里的视图控制器,它是某种形式的数据容器(人)。

您也可以在此处看到协议的值 - 请注意,SecondViewController类在第一种方法和第二种方法之间完全不会改变。它不会保护无论是与视图控制器还是Person或其他实例进行通信......只要该事件实现了可命名协议,就很高兴。

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 
+0

传递父视图控制器其子从来都不是一个好主意,因为它打破了封装,它意味着你将不能再使用该子视图其他地方,因为它希望传递具有某些属性的控制器。这是协议存在的主要原因之一。 – Rog 2011-12-22 04:40:46

+0

@Rog有什么都没有错父视图控制器传递给孩子。不理想的是让孩子期待传递给父母的东西。你说得对 - 这就是为什么我定义了上面命名的协议。为了清楚起见,我将为父母添加一个界面,显示它采用Nameable。 – Caleb 2011-12-22 04:43:59

+0

+1感谢您的帮助。 – TommyG 2011-12-22 05:16:45