Obj-C – 如何使用单例在视图控制器之间传递数据?

好吧,这是我昨晚问的一个问题的延伸。 对于如何使用各种技术在视图控制器之间传递数据,我有一点点的把握。 我想去MVC路线,创build一个Singleton类似乎是最接近MVC的概念。

基本上我创build了一个简单的应用程序与两个视图控制器和一个单身类。 我正在尝试将文本字段的值传递给UILabel。 无论出于何种原因,这是行不通的。 这是我的代码看起来像。

ViewController.h

#import <UIKit/UIKit.h> #import "Model.h" #import "ViewController2.h" @interface ViewController : UIViewController { NSString *text2pass; } @property (weak, nonatomic) IBOutlet UITextField *tf; @property (weak, nonatomic) IBOutlet UILabel *btn; - (IBAction)go:(id)sender; @end 

ViewController.m

  #import "ViewController.h" @interface ViewController () @end @implementation ViewController @synthesize tf = _tf; @synthesize btn = _btn; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *tfstring = _tf.text; NSLog(@"string = %@",tfstring); } - (void)viewDidUnload { [self setTf:nil]; [self setBtn:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. } - (IBAction)go:(id)sender { NSLog(@"btn pressed"); UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; ViewController2 *vc2 = (ViewController2 *) [storyboard instantiateViewControllerWithIdentifier:@"home"]; text2pass = _tf.text; [self passValues]; [self presentModalViewController:vc2 animated:YES]; } -(void) passValues { Model *model = [Model sharedModel]; model.passedText = text2pass; } @end 

ViewController2.h

 #import <UIKit/UIKit.h> #import "ViewController.h" @interface ViewController2 : UIViewController { NSString *passedText; } @property (nonatomic)NSString *passedValue; @property (weak, nonatomic) IBOutlet UILabel *lbl; - (IBAction)back:(id)sender; @end 

ViewController2.m

 #import "ViewController2.h" @interface ViewController2 () { NSString *passedtext; } @end @implementation ViewController2 @synthesize lbl = _lbl; @synthesize passedValue = _passedValue; - (void)viewDidLoad { // do code stuff here NSLog(@"passedText = %@",passedText); _lbl.text = passedText; [super viewDidLoad]; } - (void)viewDidUnload { [self setLbl:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. } - (IBAction)back:(id)sender { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; ViewController *vc = (ViewController *) [storyboard instantiateViewControllerWithIdentifier:@"welcome"]; [self presentModalViewController:vc animated:YES]; } @end 

Model.h

 #import <Foundation/Foundation.h> @interface Model : NSObject { NSString *passedText; } @property (nonatomic, strong) NSString* passedText; + (Model *) sharedModel; @end 

Model.m

 #import "Model.h" @implementation Model @synthesize passedText = _passedText; static Model *sharedModel = nil; + (Model *) sharedModel { @synchronized(self){ if (sharedModel == nil){ sharedModel = [[self alloc] init]; } } return sharedModel; } @end 

该项目可以从这里完整下载http://chrisrjones.com/files/KegCop-Test.zip

如果你知道为什么UILabel不显示文本字段文本让我知道。 哦,我几乎遵循这个 – > http://www.youtube.com/watch?v=ZFGgMPcwYjg&feature=plcp

你的寻址和内存pipe理是简单的…closures。 首先,绝对没有理由为此创build一个单例,但这不在这里。

其次,在声明属性的时候,(atomic,assign)是默认的,如果没有其他的指定,也就是说你的string:

 @property (nonatomic)NSString *passedValue; 

是软弱的酱油,在一会儿的时间内就可以再次分配和销毁。 声明它copystrongretain

第三,在推送的视图控制器中绝对没有提到你的单例,但是你似乎相信在不同的类中被命名为相同的对象保留了它们的值(尤其是在#import的时候)。 不是这样。 您需要引用您的单例,并将[Model sharedModel].passedText的值[Model sharedModel].passedText该文本字段中。

事实上,我把你的样本分成两行:

 //ViewController2.m #import "ViewController2.h" //actually import the singleton for access later #import "Model.h" @interface ViewController2 () { NSString *passedtext; } @end @implementation ViewController2 @synthesize lbl = _lbl; @synthesize passedValue = _passedValue; - (void)viewDidLoad { // do code stuff here NSLog(@"passedText = %@",passedText); //actually reference the singleton this time _lbl.text = [Model sharedModel].passedText; [super viewDidLoad]; } - (void)viewDidUnload { [self setLbl:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. } - (IBAction)back:(id)sender { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; ViewController *vc = (ViewController *) [storyboard instantiateViewControllerWithIdentifier:@"welcome"]; [self presentModalViewController:vc animated:YES]; } @end 

这产生了:

修复了代码

我不build议使用Singleton作为一种传递应用程序数据的好方法。 大多数应用程序很简单,这种中央访问是没有必要的,它通常会造成维护的噩梦…但是我不认为你使用单例的事实对于让你的代码工作是非常重要的。

假设你可以访问ViewController1中的数据,在你的情况下通过Model的Singleton实例(需要一个更具描述性的名字),那么你所要做的就是在ViewController2被创build和显示时传递给ViewController2,完全不需要单身人士。

一旦你创build了控制器,设置你需要的数据,然后呈现视图控制器 – 这基本上是你在做什么。

至于为什么它不工作:视图控制器被呈现,只是没有正确的数据? 还是真的有一个问题,提交控制器呢? 我将在ViewController1的go: action中设置一个断点,确保你期望的数据在文本字段中,正确地填充模型,并且正确地将值从ViewController2中的模型中拉出。

除非你删除了一些代码,否则它看起来像在ViewController1中正确地填充了Model属性,但是在ViewController2中你引用了一个本地的ivar而不是从模型中取出。

在另外一个笔记中,从现有的模式视图控制器返回的方式通常是closures该控制器,而不是重新创build初始控制器并将其放在顶部。