2016-04-14 9 views
3

期待していないときに解放されるNSObjectインスタンスに問題があります。私はNSNumber型のフォーム変数を持っています、私はインスタンスを作成し、値を設定するbutton1で、私は値を読み取るbutton2で。ボタン1でretainを呼び出さないと、変数は解放され、button2をクリックするとアプリケーションが停止し、retainを呼び出すとすべてが機能します。OSXリリース変数のDelphi XE6 ARC

これは、firefoxでDelphi XE6を使用しているOSX上です。ここで

は、いくつかのコード

今Button2click

ためButton1Click

begin 
    Fv := TNSNumber.Wrap(TNSNumber.OCClass.numberWithFloat(4.0)); 
    ShowMessage(IntToStr(Fv.retainCount)); // value is 1 
    Fv.retain; // comment out this to make it crash on button2 click 
    ShowMessage(IntToStr(Fv.retainCount)); // value is 2, or 1 without the retain 
end; 

ためのボタン

のカップルを追加し

Fv : NSNumber; 

のNSNumber

タイプのフォーム変数を定義します
begin 
    ShowMessage(IntToStr(Fv.retainCount)); // value is 1 or crashes without the retain 
ShowMessage(FloatToStr(Fv.doubleValue)); 
end; 

Button1をクリックすると、Delphiは参照カウントを減らしてFvを解放します。つまり、範囲外に出るように動作します。だから、Fvをぶら下げるようにするには、Fv.retainを追加する必要があります。保持なしでbutton2をクリックすると、クラッシュします。

私は保持する必要があります - 私はそれが必要ではないと思った、または私は何か他のものを逃していますか?正しい道に私を置くため@RudyVelthiusと@RemyLebeauへ

TIA

+1

iOSをターゲットにした場合も同じことが起こります。 Objective-Cオブジェクトをラップすると、時にはretainを呼び出す必要があり、時にはそうでない場合もあります。違いが何であるか分かりませんが、保持が必要なときに検出するのは簡単です:-) – Hans

+0

XE 6のOS XコンパイラがARCを実装していることはわかりませんでした。私はiOSとAndroidだけを考えましたか? –

+2

FWIWでは、 'numberWithFloat()'はおそらくautorelease変数を生成します(ほとんどの場合、便利なコンストラクタが行います)。これらは、次回の自動解放サイクルが実行されるまで、それらを長く保つために保持する必要があります。 –

答えて

2

感謝。

問題はデルファイの問題ではなく、客観的なCの問題です(少なくとも客観的なCの私の理解が問題です)。

TNSNumber.OCClass.numberWithFloat(4.0) 

は便利なコンストラクタです。これは自動リリースプールに追加され、次にメインループが実行されるときに解放されます。

私のデルファイインターフェイスは問題ありませんが、残念ながらそれはもはや存在しないものを指しています。コールを保持したままでオートレリース変数を保持する。これが問題であることを証明するためには、alloc/initを呼び出すことで解決しなければなりません。そう

Fv := TNSNumber.Wrap(TNSNumber.Alloc.initWithDouble(4.0)); 

Fv := TNSNumber.Wrap(TNSNumber.OCClass.numberWithFloat(4.0)); 

を交換し、保持し、そのすべての作品を削除します。

https://stackoverflow.com/a/801000/416047ここからルールがオブジェクトを返すセレクタは、単語「新しい」、「ALLOC」、 「保持」やその中の「コピー」を持っている場合

があり、その後、返されたオブジェクトを所有して完了したらそれを解放するのは、 です。

それ以外の場合は、あなたが所有していないため、公開しないでください。 が所有していないオブジェクトへの参照を保持したい場合は、そのインスタンスで - [NSObject retain]を呼び出す必要があります。そのインスタンスを所有しているので、 を呼び出すと、そのインスタンスで[NSObject release]を呼び出します。完了すると、 が呼び出されます。したがって、あなたは - [NSNumber numberWithInt:]によって返されたインスタンスを所有しておらず、完了したら-releaseを呼び出すべきではありません。 返されたインスタンスを現在のスコープ (現在のNSAutoreleasePool インスタンスの存続期間をはるかに越えて)以上に保ちたい場合は、それを保持する必要があります。

関連する問題