1

我有一些@properties 在调试器中表现得很奇怪,@synthesize然后我将它们子类化为控制器。

当我删除 @synthesize 时,@properties 的行为符合预期。

这是一个基本示例,一个ViewController名为SubClassedViewController.

视图控制器.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    NSNumber *someNumber;
}

@property (nonatomic, strong) NSNumber *someNumber;

@end

视图控制器.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize someNumber;  //Strange behavior unless I remove this line

- (void)viewDidLoad
{
    [super viewDidLoad];
    someNumber = [NSNumber numberWithInt:123];
    // Do any additional setup after loading the view, typically from a nib.
}

@end

子类视图控制器.h

#import "ViewController.h"

@interface SubClassedViewController : ViewController

@end

子类视图控制器.m

#import "SubClassedViewController.h"

@interface SubClassedViewController ()

@end

@implementation SubClassedViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

@synthesize 的行为

除非我使用self.,否则对象指向子类控制器,而不是 NSNumber:

(lldb) po someNumber
$3 = 0x07151a30 <SubClassedViewController: 0x7151a30>
(lldb) po self.someNumber
$4 = 0x08c37f20 123
(lldb) p (int)[someNumber intValue]
error: Execution was interrupted, reason: Attempted to dereference an invalid ObjC Object or send it an unrecognized selector.
The process has been returned to the state before execution.
(lldb) po (UIView*)[someNumber view]
$7 = 0x071574f0 <UIView: 0x71574f0; frame = (0 20; 320 548); autoresize = RM+BM; layer = <CALayer: 0x71575a0>>

请注意,如果我将NSLogs 放入我的代码中, someNumber 会正确指向 NSNumber;它仅在 lldb 中被标识为 SubClassedViewController(据我所知)。

没有@synthesize 的行为

如果我注释掉@synthesize并将 ViewController.m 中的 NSNumber 创建更改为:

_someNumber = [NSNumber numberWithInt:123];  //I added _ before variable name

然后我得到以下不同的行为(这是我期望的行为)

(lldb) po _someNumber
$0 = 0x0717db70 123
(lldb) po self.someNumber
$1 = 0x0717db70 123
(lldb) po self
$2 = 0x071853a0 <SubClassedViewController: 0x71853a0>

问题

  • 这是一个错误,还是我误解了什么?

如果这是一个错误(这是我的假设)......

  • 它是 Xcode、调试器还是编译器中的错误?

如果这不是错误...

  • 我正在使用 Xcode 4.6.1,它不需要我 @synthesize 东西。但是无论我是否这样做,我的应用程序的行为是否应该相同?

  • 为什么属性指向它的“所有者”会有意义?

4

1 回答 1

8

这不是“奇怪的行为”。你得到垃圾对象是因为你的代码是错误的。

删除@synthesize时,编译器会自动合成具有名称的 ivar _someNumber。这会导致您的错误代码-viewDidLoad实际上什么都不做。值得注意的是,该行

someNumber = [NSNumber numberWithInt:123];

将自动释放的对象存储到 ivar 中,这意味着它将被释放并且 ivar 将保存一个垃圾对象。这里的正确解决方法可能是说

self.someNumber = [NSNumber numberWithInt:123];

这将调用设置器并为您保留值。

此外,我建议完全删除您的 ivar 声明并删除 ivar @synthesize,然后让编译器合成您的 ivar。

于 2013-03-18T22:12:11.967 回答