0

許しをお願いします:私は初心者です。私は別の質問/回答を見ていて、このコードに出くわしました:

SpinningView *spinner = [[SpinningView alloc] initWithFrame:CGRectMake(0.0, 0.0, 20.0, 20.0)]

//ここで、SpinningViewの-initWithFrame:メソッドの実装を見てみましょう。

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
    }

    return self;
}

コードの2番目のセクションで、selfは、メッセージが送信されたインスタンスを指していると思います。その結果、「self」が検出されました。つまり、[Spin​​ningViewalloc]の結果です。(または、インスタンスを生成しませんか?)

したがって、コードの4行目でself = [super initWithFrame:frame]を呼び出すと、「spinner」に関連付けられたポインター値を再割り当てしませんか?つまり、最初の行で割り当てたメモリを放棄していませんか?または、コンパイラの誰かが、ポインタ値を変更する代わりに、メモリ値をコピーすることだけを知っていますか?または何??

ありがとう!

4

2 に答える 2

1

-initこれは、 obj-cオブジェクトのメソッドの標準的なイディオムです。割り当てられたものが何であれ、+alloc問題か​​ら返されたものだけが重要であるという考え-initです。これで、通常は-init、にあるすでに割り当てられているオブジェクトを使用します。ただし、必須ではありません。そのオブジェクトの割り当てを解除して、新しいオブジェクトを作成するのは自由です。古典的な例は、割り当て/初期化を行った場合、実際にはのインスタンスを取得せず、具体的なサブクラスを取得します。これは、が「クラスクラスタ」であるためです。したがって、呼び出すと、が返されますが、呼び出すと、そのオブジェクトが解放され、そのサブクラスの1つのオブジェクトが再割り当てされ、その新しいオブジェクトが初期化されて、返されます。selfNSString*NSString*NSString*+allocNSString*-init

もう1つの例は、自分自身をメモしようとしたクラスがある場合です。数値で初期化される不変のクラスがあるとしましょう。-initクラスの既存のインスタンスを再利用するようにを変更できます。次に例を示します(注:スレッドセーフではありません):

static NSDictionary *numberCache;

@interface MyNumber : NSObject
@property (readonly) int number;
- (id)initWithInt:(int)i;
@end

@implementation MyNumber
+ (void)initialize {
    if (self == [MyNumber class]) {
        numberCache = [[NSDictionary alloc] init];
    }
}

- (id)initWithInt:(int)i {
    // find ourself in the numberCache
    NSValue *val = [numberCache objectForKey:@(i)];
    if (val) {
        // yep, we exist. Release the just-allocated object
        [self release];
        // and retain the memoized object and stuff it back in self
        self = [[val nonretainedObjectValue] retain];
    } else if ((self = [super init])) {
        // nope, doesn't exist yet. Initialize ourself
        _number = i;
        // and stuff us into the cache
        val = [NSValue valueWithNonretainedObject:self];
        [numberCache setObject:val forKey:@(i)];
    }
    return self;
}

- (void)dealloc {
    // remove us from the cache
    [numberCache removeObjectForKey:@(_number)];
    [super dealloc];
}
@end
于 2012-12-10T20:28:42.033 に答える
0

@KevinBallardがほとんどのポイントをカバーしました。が必要な理由は、呼び出されたのと同じオブジェクトを返すことが保証されていないためです(別のオブジェクトまたはを返す可能性がありますself =)。私はあなたの質問に答え、メモリ管理の側面を拡張します:initnil

コードの2番目のセクションで、selfは、メッセージが送信されたインスタンスを指していると思います。その結果、「self」が検出されました。つまり、[Spin​​ningViewalloc]の結果です。

はい

したがって、コードの4行目でself = [super initWithFrame:frame]を呼び出すと、「spinner」に関連付けられたポインター値を再割り当てしませんか?

はい。そうではありませんspinnerspinnerとにかくこの時点では存在しません)。selfメソッド内でポインタ変数を再割り当てしています。

つまり、最初の行で割り当てたメモリを放棄していませんか?または、コンパイラの誰かが、ポインタ値を変更するのではなく、メモリ値をコピーすることだけを知っていますか?または何??

はい。MRCでは、ポインターを再割り当てするだけで、コンパイラーはポインター値を変更する以外は何もしません。ARCの場合はもっと複雑ですが、結局のところ、コンパイラはこの場合のMRCの場合と同じように動作します。つまり、ポインタを再割り当てするだけです。

あなたがそれについて考えるならば、それは本当に記憶を「放棄」することではありません。慣例により、initメソッドは、呼び出された既に保持されているオブジェクト(通常はへの呼び出しの戻り結果)の所有権を取得(「消費」)し、保持されたallocオブジェクトを返します。ただし、これら2つは同じオブジェクトである必要はありません。したがって、initメソッドが呼び出されると、そのメソッドselfはすでに保持されており、initメソッドがそれを所有していますが、次に[super init...]、を呼び出します。これは、でスーパークラスのinitメソッドを呼び出します。これによりself、メソッドは、所有self権をinit持っていたの所有権を取得します。そしてその見返りに、そのスーパークラスinitは、あなたがに割り当てた保持されたインスタンスをあなたに返しますself。あなたは「放棄」しませんでしたselfこれは、スーパークラスのメソッドに渡したためです。スーパークラスのinitメソッドは、メモリ管理(他の何かを返したい場合にリリースすることを含む)を担当するようになりました。

于 2012-12-11T02:17:59.010 に答える