xcode Obj-C - 如何使用单例在视图控制器之间传递数据?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11405636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Obj-C - How to pass data between viewcontrollers using a singleton?
提问by ipatch
Alright, so this is an extension to a question I asked last night. I have a little firmer grasp on how data can be passed between view controllers using various techniques. I wanted to go the MVC route, and creating a Singleton class seems the closest concept similar to MVC.
好的,这是我昨晚提出的问题的延伸。我对如何使用各种技术在视图控制器之间传递数据有了更深入的了解。我想走 MVC 路线,创建一个单例类似乎是与 MVC 最接近的概念。
Basically I created a simple app with two View Controllers and a singleton class. I am trying to pass the value of a text field into a UILabel. For whatever reason it isn't working. This is what my code looks like.
基本上我创建了一个简单的应用程序,其中包含两个视图控制器和一个单例类。我正在尝试将文本字段的值传递到 UILabel 中。无论出于何种原因,它都不起作用。这就是我的代码的样子。
ViewController.h
视图控制器.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
视图控制器.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
视图控制器2.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
视图控制器2.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
模型.h
#import <Foundation/Foundation.h>
@interface Model : NSObject {
NSString *passedText;
}
@property (nonatomic, strong) NSString* passedText;
+ (Model *) sharedModel;
@end
Model.m
模型.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
The project can be downloaded in its entirety from here http://chrisrjones.com/files/KegCop-Test.zip
该项目可以从这里完整下载http://chrisrjones.com/files/KegCop-Test.zip
If you know why the UILabel is not displaying the text field text let me know. Oh I pretty much followed this -> http://www.youtube.com/watch?v=ZFGgMPcwYjg&feature=plcp
如果您知道为什么 UILabel 不显示文本字段文本,请告诉我。哦,我几乎跟着这个 -> http://www.youtube.com/watch?v=ZFGgMPcwYjg&feature=plcp
回答by CodaFi
Your addressing, and memory management is just plain... off. Firstly, there's absolutely no reason to create a singleton for this, but that's beside the point here.
您的寻址和内存管理很简单……关闭。首先,绝对没有理由为此创建单例,但这不是重点。
Secondly, when declaring properties, (atomic, assign) is defaulted to if not otherwise specified, which means your string:
其次,在声明属性时,(atomic,assign) 默认为如果没有另外指定,这意味着你的字符串:
@property (nonatomic)NSString *passedValue;
is weak sauce, ripe for deallocation and destruction at a moments notice. Declare it copy
, strong
, or retain
.
是弱调味料,随时可以释放和销毁。声明它copy
, strong
, 或retain
。
Thirdly, there's absolutely no reference to your singleton in the pushed view controller, yet you seem to have the belief that objects that are named the same in different classes retain their value (especially when #import'ed). Not so. You need to reference your singleton and pull the value of [Model sharedModel].passedText
into that text field.
第三,在推送的视图控制器中绝对没有对您的单例的引用,但您似乎相信在不同类中命名相同的对象会保留它们的值(尤其是在 #import 时)。不是这样。您需要引用您的单身人士并将 的值拉[Model sharedModel].passedText
入该文本字段。
In fact, I fixed your sample in two lines:
事实上,我将您的样本分为两行:
//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
Which yields this:
这产生了:
回答by Stew
I wouldn't recommend using a Singleton as a good way to pass data around your application. Most apps are simple enough that this kind of central access is not necessary, and it usually creates a maintenance nightmare... but I don't think the fact that you're using a Singleton is actually important to getting your code working.
我不建议使用 Singleton 作为在应用程序中传递数据的好方法。大多数应用程序都很简单,不需要这种中央访问,它通常会造成维护噩梦……但我认为您使用单例的事实对于让您的代码正常工作并不重要。
Assuming you have access to the data in ViewController1, in your case through the a Singleton instance of Model (which needs a more descriptive name), then all you have to do is pass through the data to ViewController2 when it is created and presented, which eliminates the need for a Singleton at all.
假设您可以访问 ViewController1 中的数据,在您的情况下是通过 Model 的 Singleton 实例(需要一个更具描述性的名称),那么您所要做的就是在创建和呈现数据时将数据传递给 ViewController2,即完全不需要单例。
Once you create the controller, set the data you need, and then present the view controller - which is basically what you're doing anyway.
一旦你创建了控制器,设置你需要的数据,然后呈现视图控制器——这基本上就是你正在做的事情。
As to why it's not working: Is the view controller being presented, just not with the correct data? Or is there actually an issue presenting the controller at all? I would set a breakpoint in the go:
action of ViewController1, make sure the data you expect is in the textfield, correctly populates the Model and that the value is correctly pulled out of the Model in ViewController2.
至于为什么它不起作用:是否显示了视图控制器,只是没有正确的数据?或者实际上是否存在呈现控制器的问题?我会在go:
ViewController1的操作中设置一个断点,确保您期望的数据在文本字段中,正确填充模型并且该值正确地从 ViewController2 中的模型中拉出。
Unless you've removed some of the code, it looks like you correctly populate the Model property in ViewController1, but in ViewController2 you refer to a local ivar passedText
rather than pulling it from the model.
除非您删除了一些代码,否则看起来您在 ViewController1 中正确填充了 Model 属性,但在 ViewController2 中您引用的是本地 ivarpassedText
而不是从模型中提取它。
On a separate note, the way to go backfrom a presented modal view controller is usually to dismiss that controller, not to re-create the initial controller and present that over the top.
在一个单独的说明,要走的路回来从提交模式视图控制器通常是关闭那些控制器,而不是重新创建初始控制器和现在是在上面。