我一直在寻找如何做到这一点。我有2 View Controllers
。从根View Controller
(ViewControllerA
- 这是一个表视图控制器),您可以转到第二个视图控制器(ViewControllerB
)。
在ViewControllerB
中,有两个字段:contacts&的TextBody。用户完成后,可以单击“添加”。然后,这将返回ViewControllerA
。我现在要做的是,每次发生这个过程时,刚刚添加的用户ViewControllerB
的所有信息都会进入ViewControllerA
的单元格。然后,用户可以根据需要添加任意数量的单元格。
然而,我不能做的是通过视图控制器获取信息。我整个上午一直在寻找使用app delegate,singletons ??,协议,共享属性等等!但我仍然被卡住了。
我想要做的但不是每次用户点击ViewControllerB
上的“添加”,联系人和&文本被放入一个数组中。然后将此数组放入另一个数组中,该数组包含用户创建的所有较小数组?如果您有想法或类似/示例代码或教程的链接,那将非常感激!
答案 0 :(得分:2)
使用委托方法尝试以下
Download Sample Project with XIBs
Download Sample Project With Storyboard
<强> ParentViewController.h 强>
#import <UIKit/UIKit.h>
@interface ParentViewController : UIViewController {
NSMutableArray *dataArray;
}
- (void)passData:(NSMutableArray *)array;
@end
<强> ParentViewController.m 强>
#import "ParentViewController.h"
#import "ChildViewController.h"
@implementation ParentViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Initialise the mutable array.
dataArray = [[NSMutableArray alloc] init];
}
- (IBAction)btnGoToSecondView:(id)sender {
ChildViewController *secondVC = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];
secondVC.delegate = self;
[self presentViewController:secondVC animated:YES completion:nil];
}
- (void)passData:(NSMutableArray *)array {
[dataArray addObject:array];
NSLog(@"Data Passed = %@",dataArray);
}
@end
<强> ChildViewController.h 强>
#import <UIKit/UIKit.h>
#import "ParentViewController.h"
@class ParentViewController;
@interface ChildViewController : UIViewController {
NSMutableArray *tempArray;
}
@property (strong, nonatomic) IBOutlet UITextField *txtContact;
@property (strong, nonatomic) IBOutlet UITextField *txtTextBody;
@property(nonatomic, assign) ParentViewController *delegate;
@end
<强> ChildViewController.m 强>
@implementation ChildViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Initialise the mutable array.
tempArray = [[NSMutableArray alloc] init];
}
- (IBAction)btnPassDataBack:(id)sender {
if([self.delegate respondsToSelector:@selector(passData:)]) {
[tempArray addObject:_txtContact.text];
[tempArray addObject:_txtTextBody.text];
[self.delegate passData:tempArray];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidUnload {
[self setTxtContact:nil];
[self setTxtTextBody:nil];
[super viewDidUnload];
}
@end
如果你正在使用故事板,那么创建一个ParentViewController segue ChildViewController并在我的样本中给它一个identifier
showChildView
然后使用以下代码设置委托
// Calling the segue to go to the child view and setting up the delegate.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"showChildView"]) {
ChildViewController *childVC = segue.destinationViewController;
childVC.delegate = self;
}
}
然后关闭回ParentViewController使用以下代码(来自我的样本)
- (IBAction)btnPassDataBack:(id)sender {
if([self.delegate respondsToSelector:@selector(passData:)]) {
[tempArray addObject:_txtContact.text];
[tempArray addObject:_txtTextBody.text];
[self.delegate passData:tempArray];
}
[self.navigationController popToRootViewControllerAnimated:YES];
}
答案 1 :(得分:1)
我建议使用NSMutableDictionary的单例实例,因为它们已经多次保存了您的确切情况(包括自定义框架和UITabBarControllers)。这是我目前用来实现单例的一个例子。这种方法也是ARC安全的
mySingleton.h
#import <Foundation/Foundation.h>
@interface mySingleton : NSObject {
}
+ (NSMutableDictionary *) myMutableDict;
@end
mySingleton.m
#import "mySingleton.h"
@implementation mySingleton
+ (NSMutableDictionary *)myMutableDict
{
static NSMutableDictionary *singletonInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singletonInstance = [[NSMutableDictionary alloc]init];
});
return singletonInstance;
}
@end
只要在所有视图控制器中包含mySingleton.h,您就可以通过[mySingleton myMutableDict]
访问数据。例如:[[mySingleton myMutableDict] setObject:myObject forKey:myKey];
答案 2 :(得分:1)
如果信息真的是“全局” - 它在整个应用程序中只有一个实例 - 那么你应该像DB80Buckeye建议的那样创建一个单例。
如果信息是真正属于ViewController1的东西,并且你希望它在ViewController2中被修改(即ViewController2实际上是ViewController1的一部分,它恰好在另一个屏幕上),那么你应该将它作为一部分传递给它ViewController2的构造函数。
-(void)view_controller_1_that_push_view_controller_2_onto_the_stack {
ViewController2* vc2 = [[ViewController2 alloc] initWithInformation:your_information];
[self.navigationController pushViewController:vc2 animated:YES];
}
@interface ViewController2
-(id)initWithInformation:(YourInformationClass*)info;
@end
另一种方法是使用通知。
答案 3 :(得分:1)
这里有两种方法。执行此操作的标准模式是委派。你不需要单身人士。 ViewControllerA
管理并列出您的数据。 ViewControllerB
不需要知道所有这些数据,因此没有理由通过单例等公开它。
在ViewControllerB
的头文件中创建委托协议。像这样:
@protocol ViewControllerBDelegate
- (void)addContact:(NSString *)contact withBody:(NSString *)textBody;
@end
现在,指定ViewControllerA
将在其标头中实现委托协议:
@interface ViewControllerA : UIViewController <ViewControllerBDelegate>
不要忘记在ViewControllerB.h
标题的顶部导入ViewControllerA
。
在ViewControllerA
的实现中,实现您在协议中指定的委托方法:
- (void)addContact:(NSString *)contact withBody:(NSString *)textBody {
[self.someArray addObject:[[SomeObject alloc] initWithContact:contact body:textBody]];
[self.tableView reloadData];
}
这显然只是一个例子 - 不确定你是如何管理你的数据结构的,并且最好在有意义的地方插入单元格。
在ViewControllerB
的标题中声明委托引用:
@property (weak, nonatomic) id<ViewControllerBDelegate> delegate;
当您出示ViewControllerB
时,请将ViewControllerA
设为代表。
ViewControllerB *b = [[ViewControllerB alloc] init...];
b.delegate = self;
在ViewControllerB
中的添加按钮触发的选择器中,在将视图控制器从导航堆栈中弹出之前回调代理:
[self.delegate addContact:contact withBody:text];
其中contact
和text
是用户输入的值。
也可以使用块而不是委托,但原理是相同的 - 让第二个视图控制器只负责输入,在您的情况下,并将其传递回管理数据的视图控制器。 / p>
答案 4 :(得分:1)
或者代表建议使用以下内容: ViewControllerA.h:
@property (nonatomic, strong) ViewControllerB* viewControllerB;
在ViewControllerA.m中
if (!self.viewControllerB)
{
self.viewControllerB = [[ViewControllerB alloc] initWithNibName: @"ViewControllerBr" bundle: nil];
}
[self.navigationController pushViewController: self.viewControllerB
animated: YES];
...
- (void) viewWillAppear: (BOOL) animated
if (self.viewControllerB)
{
NSString* contact = self.viewControllerB.contact;
NSLog(@"%@", contact);
}
...