我知道很多地方已经涵盖了这个主题,但是在经历不同的答案时,我找不到适合我的情况的解决方案。
基本上我想做的事情很简单。我有一个带有表视图的视图控制器,以及一个+按钮,用于触发第二个视图控制器,用户可以在其中输入一个名称,然后将该名称添加到第一个视图控制器表视图中。想想iPhone上的联系人,您可以在其中添加新人(或亚马逊,您可以添加新的信用卡)。
我的问题是 - 将此字符串(在本例中)返回到表所在的视图控制器的最佳方法是什么?
人们建议使用NSDefaults,Delegate或singleton,这些对于这种情况都不是很好(每个都是出于自己的原因)。我真的只需要返回一个简单的字符串。
感谢您的帮助。
答案 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