@pronties在@synthesized时在调试器中出现意外行为,然后在子类中访问

Aar*_*ger 1 objective-c ios lldb

我有一些@properties在调试器中表现得很奇怪@synthesize,然后继承控制器.

当我删除@synthesize时,@ property会按预期运行.

这是一个基本的例子,一个ViewController叫做的子类SubClassedViewController.

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    NSNumber *someNumber;
}

@property (nonatomic, strong) NSNumber *someNumber;

@end
Run Code Online (Sandbox Code Playgroud)

ViewController.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
Run Code Online (Sandbox Code Playgroud)

SubClassedViewController.h

#import "ViewController.h"

@interface SubClassedViewController : ViewController

@end
Run Code Online (Sandbox Code Playgroud)

SubClassedViewController.m

#import "SubClassedViewController.h"

@interface SubClassedViewController ()

@end

@implementation SubClassedViewController

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

@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>>
Run Code Online (Sandbox Code Playgroud)

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

没有@synthesize的行为

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

_someNumber = [NSNumber numberWithInt:123];  //I added _ before variable name
Run Code Online (Sandbox Code Playgroud)

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

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

问题

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

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

  • 它是Xcode,调试器或编译器中的错误吗?

如果这不是一个bug ...

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

  • 为什么房产指向其"所有者"是否有意义?

Lil*_*ard 8

这不是"奇怪的行为".您正在获取垃圾对象,因为您的代码是错误的.

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

someNumber = [NSNumber numberWithInt:123];
Run Code Online (Sandbox Code Playgroud)

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

self.someNumber = [NSNumber numberWithInt:123];
Run Code Online (Sandbox Code Playgroud)

这将调用setter并为你保留值.

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