在 Objective C 中切换视图控制器时返回空值的变量
variables returning null value upon switching View Controllers in Objective C
我是 objective C 编程的新手,正在研究在视图控制器之间移动数据。我想知道 ViewController 之间的双向数据流(变量)是否可能。
我可以向后移动数据(到 presentingViewController / sourceViewController)但是我不能向前移动数据(到 presentedViewController / destinationViewController)。
我做了一个简单的案例场景(涉及字符串以获得想法的原理),它涉及使用 [=36= 在 destinationViewController 上更新 UItextField ]UILabel 在 sourceViewController 中,反之亦然。
我无法使用 UILabel 更新 UITextField,但可以使用 更新 UILabel ]UITextField。
我已经制作了不同语句的日志来跟踪变量值,但是当我将 ViewControllers 变量 Data returns 切换为 null 时,即使它们被标记为 strong.
能否请您提供任何指导,它一直在撕裂我的脑海,还是我遗漏了一些明显的东西?我不明白为什么当我切换 ViewControllers 时我总是得到一个(空)值(在我的 NSLog 中)。
- 我的 sourceViewController / presentingViewController 命名为 "ViewController."
- 我的 destinationViewController / presentedViewController 被命名为 "Gears2ViewController".
我在下面附上了我的代码文件:
ViewController.h:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *outputLabel;
- (IBAction)ExitToHere:(UIStoryboardSegue *)sender;
@end
ViewController.m:
#import "ViewController.h"
#import "Gear2ViewController.h"
@interface ViewController ()
- (IBAction)changeItem:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)changeItem:(id)sender {
Gear2ViewController *G2VC=[[Gear2ViewController alloc] init];
G2VC.peterSido=[NSString stringWithFormat:@"%@",self.outputLabel.text];
[self performSegueWithIdentifier:@"toGear2" sender:self];
NSLog(@"ViewController UILabel reads %@",G2VC.peterSido);
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
}
- (IBAction)ExitToHere:(UIStoryboardSegue *)sender {
}
@end
战争机器2ViewController.h:
#import <UIKit/UIKit.h>
#import "ViewController.h"
@interface Gear2ViewController : UIViewController
@property (strong, nonatomic) NSString *peterSido;
@end
战争机器2ViewController.m:
@interface Gear2ViewController ()
@property (strong, nonatomic) IBOutlet UITextField *updatedOutput;
- (IBAction)updateOutput:(id)sender;
@end
@implementation Gear2ViewController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"Gears2ViewController ViewDidAppear reads %@",self.peterSido);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Gears2ViewController ViewDidLoad responds %@",self.peterSido);
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)updateOutput:(id)sender {
self.peterSido = self.updatedOutput.text;
((ViewController *)self.presentingViewController).outputLabel.text = self.peterSido;
NSLog(@"Gears2View Controller updating ViewController UILabel reads %@",self.peterSido);
}
@end
NSLog:
2015-06-29 18:52:58.798 testerBeta[21735:645772] Gears2ViewController ViewDidLoad responds (null)
2015-06-29 18:52:58.799 testerBeta[21735:645772] ViewController UILabel reads I like Pie
2015-06-29 18:52:59.317 testerBeta[21735:645772] Gears2ViewController ViewDidAppear reads (null)
2015-06-29 18:53:12.651 testerBeta[21735:645772] Gears2View Controller updating ViewController UILabel reads No I dont
很长但提前致谢!!!
你想传递prepareForSegue:
中的数据,像这样:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:@"toGear2"])
{
Gear2ViewController *controller = (Gear2ViewController *)segue.destinationViewController;
controller.peterSido = self.outputLabel.text;
}
}
原因是 segue 为您实例化呈现的视图控制器,然后您设置 segue 将呈现的实例化视图控制器的 属性。
要传回数据,您可以使用 unwind segue,它可以从呈现的视图控制器的 属性.
中获取值
- (IBAction)unwindFromGear2:(UIStoryboardSegue *)segue
{
Gear2ViewController *controller = (Gear2ViewController *)segue.sourceViewController;
self.outputLabel.text = controller.peterSido;
}
这是通过 segues 来回传递数据的正确方法。 Gear2ViewController 不应该 在其 presentingViewController 上设置属性。
更新:
测试 属性 不是 nil 的首选方法是这样的:
if (self.peterSido)
{
self.updatedOutput.text = self.peterSido;
}
else // No need for if test here
{
self.updatedOutput.text = @"";
}
这是长格式,但赋值和 if 测试可以更简洁地写成:
self.updatedOutput.text = self.peterSido ?: @"";
当您将任何变量声明为@属性 时,您需要将其合成到.m 文件中。
您已将 outputLabel 声明为 @属性 但您错过了在 .m 文件中合成它。
当您合成任何变量时,它允许您获取和设置它的值。
去做对你有帮助。
谢谢。
我是 objective C 编程的新手,正在研究在视图控制器之间移动数据。我想知道 ViewController 之间的双向数据流(变量)是否可能。 我可以向后移动数据(到 presentingViewController / sourceViewController)但是我不能向前移动数据(到 presentedViewController / destinationViewController)。
我做了一个简单的案例场景(涉及字符串以获得想法的原理),它涉及使用 [=36= 在 destinationViewController 上更新 UItextField ]UILabel 在 sourceViewController 中,反之亦然。 我无法使用 UILabel 更新 UITextField,但可以使用 更新 UILabel ]UITextField。 我已经制作了不同语句的日志来跟踪变量值,但是当我将 ViewControllers 变量 Data returns 切换为 null 时,即使它们被标记为 strong.
能否请您提供任何指导,它一直在撕裂我的脑海,还是我遗漏了一些明显的东西?我不明白为什么当我切换 ViewControllers 时我总是得到一个(空)值(在我的 NSLog 中)。
- 我的 sourceViewController / presentingViewController 命名为 "ViewController."
- 我的 destinationViewController / presentedViewController 被命名为 "Gears2ViewController".
我在下面附上了我的代码文件:
ViewController.h:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *outputLabel;
- (IBAction)ExitToHere:(UIStoryboardSegue *)sender;
@end
ViewController.m:
#import "ViewController.h"
#import "Gear2ViewController.h"
@interface ViewController ()
- (IBAction)changeItem:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)changeItem:(id)sender {
Gear2ViewController *G2VC=[[Gear2ViewController alloc] init];
G2VC.peterSido=[NSString stringWithFormat:@"%@",self.outputLabel.text];
[self performSegueWithIdentifier:@"toGear2" sender:self];
NSLog(@"ViewController UILabel reads %@",G2VC.peterSido);
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
}
- (IBAction)ExitToHere:(UIStoryboardSegue *)sender {
}
@end
战争机器2ViewController.h:
#import <UIKit/UIKit.h>
#import "ViewController.h"
@interface Gear2ViewController : UIViewController
@property (strong, nonatomic) NSString *peterSido;
@end
战争机器2ViewController.m:
@interface Gear2ViewController ()
@property (strong, nonatomic) IBOutlet UITextField *updatedOutput;
- (IBAction)updateOutput:(id)sender;
@end
@implementation Gear2ViewController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"Gears2ViewController ViewDidAppear reads %@",self.peterSido);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Gears2ViewController ViewDidLoad responds %@",self.peterSido);
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)updateOutput:(id)sender {
self.peterSido = self.updatedOutput.text;
((ViewController *)self.presentingViewController).outputLabel.text = self.peterSido;
NSLog(@"Gears2View Controller updating ViewController UILabel reads %@",self.peterSido);
}
@end
NSLog:
2015-06-29 18:52:58.798 testerBeta[21735:645772] Gears2ViewController ViewDidLoad responds (null)
2015-06-29 18:52:58.799 testerBeta[21735:645772] ViewController UILabel reads I like Pie
2015-06-29 18:52:59.317 testerBeta[21735:645772] Gears2ViewController ViewDidAppear reads (null)
2015-06-29 18:53:12.651 testerBeta[21735:645772] Gears2View Controller updating ViewController UILabel reads No I dont
很长但提前致谢!!!
你想传递prepareForSegue:
中的数据,像这样:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:@"toGear2"])
{
Gear2ViewController *controller = (Gear2ViewController *)segue.destinationViewController;
controller.peterSido = self.outputLabel.text;
}
}
原因是 segue 为您实例化呈现的视图控制器,然后您设置 segue 将呈现的实例化视图控制器的 属性。
要传回数据,您可以使用 unwind segue,它可以从呈现的视图控制器的 属性.
中获取值- (IBAction)unwindFromGear2:(UIStoryboardSegue *)segue
{
Gear2ViewController *controller = (Gear2ViewController *)segue.sourceViewController;
self.outputLabel.text = controller.peterSido;
}
这是通过 segues 来回传递数据的正确方法。 Gear2ViewController 不应该 在其 presentingViewController 上设置属性。
更新:
测试 属性 不是 nil 的首选方法是这样的:
if (self.peterSido)
{
self.updatedOutput.text = self.peterSido;
}
else // No need for if test here
{
self.updatedOutput.text = @"";
}
这是长格式,但赋值和 if 测试可以更简洁地写成:
self.updatedOutput.text = self.peterSido ?: @"";
当您将任何变量声明为@属性 时,您需要将其合成到.m 文件中。 您已将 outputLabel 声明为 @属性 但您错过了在 .m 文件中合成它。 当您合成任何变量时,它允许您获取和设置它的值。 去做对你有帮助。
谢谢。