1

以前にも同様の質問がありましたが、これらの回答で現在の問題を解決することはできませんでした。

状況:

CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
    //Calculate Average from Total and Pulse
    Total /= Pulse;
    [Trigger setValue:Total];
};

Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
[Array addObject:Object];       //Adds to collection.

おそらくすでに理解しているように、目前の問題は保持サイクルです。
Objectブロックへの参照をに保持しaddCallback、ブロックdoAverageはへの参照を保持しますObject

Object複数のオブジェクトに変数を再利用したいので、インスタンス変数を使用することは問題外です。(一時変数)。
ローカル変数を使用すると、保持カウントが発生します。
また、コールバックが実際に呼び出されると、何らかの理由でnilになる__block CustomType *Objectため、使用も機能しません。Trigger

何か案は?

私にはその場しのぎの解決策がありますが、それはかなり...ハッキーなようです。

4

5 に答える 5

1

すでに述べたように、この答えはかなりハッキーであり、誰かが私をより良い方向に向けることができれば私は非常に嬉しいです。
明らかに、変数と組み合わせたプリミティブデータ型が__blockうまくいきますが、これは少し複雑です。

void *Ptr;                //Variable for Block.
__block CustomType *Obj;  //Function variable, mutable by block.
BOOL (^doAverage)(void *, int, int) = ^(void *Trigger, int Total, int Pulse) {
    CustomType *T = (CustomType *)Trigger;  //Conversion
    //Calculate Average from Total and Pulse
    Total /= Pulse;
    [T setValue:Total];
};

//Convenience method.
CustomObject *(^Add)(CustomObject *) = ^(CustomObject *)NewObject {
    [Array addObject:NewObject];
    Obj = NewObject; //Assigns to the local block-Variable.
    return Obj;
};

Ptr = Add([CustomObject CreateObject]); //Creates the Object, and adds it to the array.
[Obj addCallback:^{ return doAverage(Ptr, 56, 32); }];

はプリミティブ型であるためPtr、保持されず、解放する必要はありません。同時に、問題のオブジェクトのアドレスを想定し、それによってそれを兼ねます。

オブジェクトが解放されると、ポインターのあるブロックも解放され、すべてが正常になります。ブロックが呼び出されたら、ポインタを問題の型にキャストする必要がありますが、それは小さな問題にすぎません。

Addもちろんオプションですが、構文は好きではありませんPtr = Obj = [CustomObject CreateObject];

于 2012-12-21T12:01:15.843 に答える
1

いくつかのこと。まず、あなたの方法を見てみたいと思いますaddCallback:。正しく実装していない可能性があります。たとえば、後で使用するためにブロックを保存する場合は、それをコピーする必要があります。それが正しくない場合、残りの部分に対するすべての賭けは無効になります。

また、__ block CustomType * Objectの使用も機能しません。これは、何らかの理由で、コールバックが実際に呼び出されると、トリガーがnilになるためです。

つまり、もしそうなら、それはあなたがどこかnilに割り当てられnilたことを意味します。Object

于 2012-12-22T00:57:14.627 に答える
1
CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};

Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];

テイラーは->「しかし、私が欲しいのは、問題の「オブジェクトの保持されていないコピー」であり、対応するオブジェクトの割り当てが解除されると「失われる」でしょう。」

addCallback([^ {} copy]);。の内部または内部でコピーを使用しない限り、このコードは保持サイクルを引き起こさないようです。

コピーがコードで使用されているのは正確にはどこですか?addCallbackの内部?これが次のような場合:

addCallback(o) {

o = [o copy];
o();

then do a [o release]; when you done with a block object.. do not release it in dealloc()
} 

コピーをどこでも使用したことがない場合は、心配する必要はありません。すべてがスタックで発生します。つまり、グローバルでない限り、保持サイクルはまったくありません。

小売サイクルがある場合は、__ block __weakなどを使用せず、代わりにブロックの最後にあるオブジェクトを解放してください。コピーや保持サイクルがないことに注意してください。

于 2013-01-14T05:18:17.473 に答える
0

展開ターゲットが少なくともiOS5(またはOS X 10.7)である場合は、「弱参照のゼロ化」を使用できます。

CustomType *object = [CustomType makeObject];
__weak CustomType *weakObject = object;
[object addCallback:^{
    CustomType *strongObject = weakObject;
    if (strongObject)
        return doAverage(weakObject, 56, 32);
    else
        return 0;
}];

(「ファクトリメソッド」の名前のmakeObject代わりにを使用しました。名前に「create」が含まれるメソッドは、自動解放されたオブジェクトではなく、(+ 1)保持カウントオブジェクトを返すことが期待されるためです。)CreateObject

参照は__weak保持カウントをインクリメントしないため、保持サイクルは作成されません。objectそれへの最後の強い参照がなくなったためにが破棄された場合、はweakSelfに設定されnilます。ブロック内に強力な参照が作成されます。これは、オブジェクトがまだ存在する場合はそのオブジェクトを指し、存在nilしない場合はオブジェクトを指します。

コードが正しく理解されていれば、オブジェクトが解放されているとコールバックは呼び出されません。その場合、__unsafe_unretained参照で十分です(iOS 4でも機能します)。

CustomType *object = [CustomType makeObject];
__unsafe_unretained CustomType *unsafeObject = object;
[object addCallback:^{
    return doAverage(unsafeObject, 56, 32);
}];
于 2012-12-21T12:54:24.400 に答える
-3

オブジェクトを次のように宣言してみてください

__weak CustomType *Object
于 2012-12-21T12:01:05.787 に答える