【问题标题】:variables returning null value upon switching View Controllers in Objective C在Objective C中切换视图控制器时返回空值的变量
【发布时间】:2015-06-29 16:55:20
【问题描述】:

我是使用 Objective C 编程的新手,并且正在研究在视图控制器之间移动数据。我想知道 ViewControllers 之间的双向数据流(变量)是否可行。 我可以向后移动数据(到presentingViewController / sourceViewController),但是我不能向前移动数据(到presentingViewController / destinationViewController)。

我对此做了一个简单的案例场景(涉及字符串以获得概念的原理),它涉及使用 UItextField 更新destinationViewController 上的 UILabel sourceViewController 反之亦然。 我不能使用 UILabel 更新 UITextField,但可以使用 UITextField 更新 UILabel。 我已经制作了不同语句的日志来跟踪变量值,但是当我切换 ViewControllers 时,即使它们被标记为强,变量 Data 也会返回 null。

您能否提供任何指导,它一直在我的脑海中撕裂,还是我错过了一些明显的东西?当我切换 ViewControllers 时,我不明白为什么我总是(在我的 NSLog 中)得到一个(空)值。

  • 我的 sourceViewController / presentingViewController 被命名为“ViewController”。
  • 我的destinationViewController/presentViewController 被命名为“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

Gears2ViewController.h:

#import <UIKit/UIKit.h>
#import "ViewController.h"

@interface Gear2ViewController : UIViewController
@property (strong, nonatomic) NSString *peterSido;
@end

Gears2ViewController.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

相当冗长,但在此先感谢!!!

【问题讨论】:

  • 传递的值为null的原因是因为你实例化了自己的Gear2 vc,在你实例化的vc上设置了一个值,然后segue实例化了不同的Gear2 vc。您自己的 Gear2 vc 未被使用,也从未出现过。同时,segue 的 vc 属性为空。我将在我的回答中向您展示如何正确设置 segue 的视图控制器属性。

标签: objective-c variables uiviewcontroller null segue


【解决方案1】:

你想传递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;
}

这是通过 segue 来回传递数据的正确方法。 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 ?: @"";

【讨论】:

  • 将代码输入 -(void) prepareForSegue 方法不起作用,但是如果我将该方法分配给按钮 - (IBAction) changeItem,然后是 [self performSegueWithIdentifier:@"toGear2" sender:self],然后在目标视图控制器中实现了它工作的 viewDidAppear 方法。也许我系统上的 -(void) prepareForSegue 有问题。谢谢你救了我。
  • 效果很好,比我写的要短得多。遇到了符号但不明白,现在我明白了。所以基本上if(self.peterSido=self.peterSido)if(self.peterSido) 是一样的,我更喜欢后者,更短更简单。再次感谢。
  • 不一样。 if (x == x) 测试是否相等,并且始终为真,即使是 0 == 0。if (x)if (x != 0) 的简写,测试 not nil。
  • 感谢您的更新,尝试查找但实际上找不到它的解释。
【解决方案2】:

当您将任何变量声明为 @property 时,您需要在 .m 文件中对其进行综合。 您已将 outputLabel 声明为 @property,但您错过了在 .m 文件中合成它。 当您合成任何变量时,它允许您获取和设置它的值。 这样做会对你有帮助。

谢谢。

【讨论】:

  • 将尝试手动@synthesize,我相信 Xcode 会为我添加到 ViewController 文件的任何属性运行该函数。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-06
  • 1970-01-01
  • 2014-06-30
  • 1970-01-01
  • 2019-05-28
  • 2017-11-24
相关资源
最近更新 更多