1

デバッガーでいくつかの @properties が奇妙に動作し@synthesize、コントローラーをサブクラス化すると、それらが異常に動作します。

@synthesize を削除すると、@properties は期待どおりに動作します。

これは基本的な例で、 というViewControllerサブクラスSubClassedViewControllerです。

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    NSNumber *someNumber;
}

@property (nonatomic, strong) NSNumber *someNumber;

@end

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

SubClassedViewController.h

#import "ViewController.h"

@interface SubClassedViewController : ViewController

@end

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

コードに sを入れるとNSLog、 someNumber は NSNumber を正しく指すことに注意してください。lldb では SubClassedViewController としてのみ識別されます (私が知る限り)。

@synthesize がない場合の動作

@synthesizeViewController.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 宣言を完全に削除し、@synthesizeも削除して、コンパイラーに ivar を合成させることをお勧めします。

于 2013-03-18T22:12:11.967 に答える