【问题标题】:Is a class property accessible after initialisation and available in a callback method是初始化后可访问的类属性并在回调方法中可用
【发布时间】:2013-07-19 21:10:20
【问题描述】:

也许是一种复杂的措辞方式。

应该发生的过程:

  1. FirstViewController 加载
  2. 您单击一个按钮,该按钮显示一个带有partial curl 的新视图
  3. 你选择了一个 UITableCell
  4. 您在FirstViewController 中设置了任何已单击单元格的属性
  5. FirstViewController 的回调方法中,您可以访问该属性以确定下一阶段的执行。

但是,当设置属性并尝试检索它时,它会以NULL 的形式返回。这是我尝试设置它的方式:

FirstViewController.h:

@interface FirstViewController : UIViewController
{
    NSString *navOption;
}
@property(nonatomic, retain) NSString *navOption;

FirstViewController.m(回调):

@synthesize navOption;

-(void)callBackForNav{
    NSLog(@"Inside callback: %@", navOption);
}

SecondViewController里面:

FirstViewController *dw = [[FirstViewController alloc] 
    initWithNibName:nil bundle:nil];
dw.navOption = @"Filter Results";

我希望在回调 navOption 中等于过滤结果,但是它输出为 NULL。有什么想法我哪里出错了吗?

【问题讨论】:

  • 它不是“类属性”,而是别的东西。它只是一个“财产”。此外,您应该删除 @synthesize 代码行,因为它不再需要。不过,这不会导致问题,我会将其发布到答案中。
  • @AbhiBeckert 对不起,我对此很陌生。所以你认为问题出在其他地方?

标签: ios objective-c properties


【解决方案1】:

如果我理解这一点,您将看到 FirstViewController,然后在上面显示 SecondViewController。我在代码中分配navOption 时看到的问题是SecondViewController 是创建一个新的FirstViewController,而不是引用旧的。因此,当您弹出堆栈并返回到原始的 FirstViewController 时,并没有在其上设置数据,因为它是一个不同的实例。

现在我看到您正在尝试对类属性做一些事情,但我不确定这是否是正确的方法,您应该专注于获取对原始视图控制器的引用并在那里设置属性。

如果你真的想要一个类“属性”,你必须做这样的事情。

// MyClass.h
@interface MyClass {
}

+(NSObject*) theObject;

// MyClass.m
+(NSObject*) theObject
{
  static NSObject* staticObject = nil;

  if (staticObject == nil)
  {
    // create object
  }

  return staticObject;
}

【讨论】:

  • 嘿,谢谢你的回答!如何引用原版FirstViewController
  • 您可以在SecondViewController 上创建一个引用第一个属性的属性,或者您可以在SecondViewController 上创建一个协议/委托并让第一个实现它。
【解决方案2】:

将@synthesize 更改为

@synthesize navOption = navOption;

默认情况下,@synthensize 创建一个带有下划线前缀的实例变量。所以navOption 属性没有使用navOption 实例变量。相反,它使用了一个名为 _navOption 的实例变量。

您真正应该做的是删除实例变量和@synthesize 并始终使用该属性。

FirstViewController.h:

@interface FirstViewController : UIViewController

@property(nonatomic, retain) NSString *navOption;

FirstViewController.m(回调):

-(void)callBackForNav{
    NSLog(@"Inside callback: %@", self.navOption);
}

【讨论】:

  • 只有在极少数情况下才需要这样做。在这种情况下,它是不需要的。
  • 您的第一个陈述不正确。没有显式实例变量的@synthesize navOption; 将属性合成为navOption 没有下划线,比较stackoverflow.com/a/14556476/1187415
  • @MartinR 我不这么认为。没有检查是否有特殊情况(可能有......)但我怀疑@synthesize navOption; 相当于@syntesize navOption = _navOption;。它使用 下划线。不过,这可能取决于 Xcode 的版本。
  • @AbhiBeckert:仅当您省略 synthesize 语句时。比较stackoverflow.com/a/14556476/1187415
  • 我又测试了一遍,我在stackoverflow.com/a/14556476/1187415说的还是有效的。如果您省略 synthesize 语句,则该属性将使用下划线进行综合。如果你写的@synthesize navOption; 没有明确的变量名,那么综合属性没有下划线(出于兼容性原因)。
【解决方案3】:

使用此代码:

@interface FirstViewController : UIViewController
{
    NSString *navOption;
}
@property(nonatomic, retain) NSString *navOption;

您正在声明一个实例变量“navOption”和一个属性“navOption”。它们是两个完全独立的变量。

这行代码:

dw.navOption = @"Filter Results";

设置 navOption 属性的值。设置实例变量的语法是dw->navOption = @"Filter Results"

这行代码:

NSLog(@"Inside callback: %@", navOption);

正在读取您从未设置过的实例变量。读取属性的代码是self.navOption,而不仅仅是navOption

解决方案是不要使用实例变量,因为除非在您需要极高性能的情况下(在这种情况下,您应该使用 C 而不是 Objective-C),否则不建议使用它们。基本上,实例变量是现代编程中很少使用的语言特性,但它仍然存在并且过去经常使用。


将您的 NSLog 更改为打印 self.navOption 并删除这两行代码:

NSString *navOption; // in the .h file
@synthesize navOption; // in the .m file.

【讨论】:

  • 感谢您抽出宝贵时间发布此内容。我已经删除了 NSString 和 @synthesises 并将 NSLog 更改为 self.navOption 但是它仍然返回 null,我很抱歉这么痛苦 - 我仍在尝试学习 Obj-C 的绳索
  • @JoshBoothe 那么您的代码中的其他地方一定有问题。进行我建议的更改后,请使用您正在使用的代码更新您的问题。
  • 我只是在我设置属性的地方放了一个 NSLog:NSLog(@"whats is it: %@", dw.navOption);,它返回了正确的值。有趣的是,回调的日志是在我刚刚向您展示的日志之前调用的。这和问题有关系吗?
  • 设置属性self.navOption 设置相应的实例变量(在本例中为navOption)。即使不推荐,直接读取实例变量navOption 也会产生与调用self.navOption 相同的结果(通过getter 函数读取相同的变量)。 "...读取你从未设置过的实例变量..."是错误的。
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 2022-08-14
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多