6

-init私たちのメソッドがメッセージのみを呼び出すと仮定すると、メッセージングが効果がないselfかどうかを確認するのが一般的であるのはなぜですか?self != nilnil

次のような初期化子があるとしましょう。

- (id)init
{
    self = [super init];
    if (self) {
        [self doThis];
        [self setFoo:@"Bar"];
    }

    return self;
}

チェックする代わりにself、次のように書くことができます。

- (id)init
{
    self = [super init];
    [self doThis];
    [self setFoo:@"Bar"];

    return self;
}

何らかの理由で[super init]が戻った場合nil、私が知る限り、メソッドの結果に違いはありません。では、なぜこのチェックを常に実行するのでしょうか。

4

2 に答える 2

7

nilにメッセージを送信することはできますが、nilのインスタンス変数にアクセスすることはできません。EXC_BAD_ACCESS例外が発生します。

インスタンス変数を持つクラスを考えてみましょう。

@implementation MyObject {
    int instanceVariable;
}

- (id)init {
    self = [super init];
    instanceVariable = 7;
    return self;
}

[super init]この例でnilを返すとどうなりますか?instanceVariablenullポインタからアクセスしようとすると、例外が発生します。

インスタンス変数にアクセスしていない場合でも、をチェックしないと、他のことが確実にうまくいかない可能性がありますself == nil。割り当てられたメモリまたはファイルハンドルを簡単にリークmallocしたり、nilを予期していないメソッドに自分自身を渡したりすることができます。

他の回答では、nilをチェックしないと、オブジェクトがリークする可能性があると主張しています。例えば:

@implementation MyObject

@synthesize someProperty; // assume it's an NSObject *

- (id)init {
    self = [super init];
    [self setSomeProperty:[[NSObject alloc] init]];
    return self;
}

これは、たとえselfゼロであっても、ARCではリークしません。手動参照カウント(MRC)ではself、+ 1保持カウントのバランスを取るものがないため、この例はnilであるかどうかに関係なくリークし[NSObject alloc]ます。

MRCでそれを行う適切な方法は次のとおりです。

- (id)init {
    self = [super init];
    [self setSomeProperty:[[[NSObject alloc] init] autorelease]];
}

またはこれ:

- (id)init {
    self = [super init];
    NSObject *object = [[NSObject alloc] init];
    [self setSomeProperty:object];
    [object release];
    return self;
}

selfゼロであるかどうかにかかわらず、どちらもリークしません。

このようにsetterメソッドをバイパスすると、isnilの場合にクラッシュしますself

- (id)init {
    self = [super init];
    _someProperty = [[NSObject alloc] init];
    return self;
}
于 2012-08-17T07:22:17.750 に答える
0

[super init]が順番にnilを返した場合、自分自身を返すとnilを返すため、使用されないオブジェクトをさらに割り当てる可能性があります。したがって、これらのオブジェクトは解放されません。

于 2012-08-17T07:22:35.740 に答える