OSX上的Delphi XE6 ARC发布变量

时间:2016-04-14 12:19:08

标签: macos delphi firemonkey delphi-xe6

当我不期待时,我有一个NSObject实例被释放的问题。我有一个NSNumber类型的表单变量,在button1我创建一个实例并设置一个值,在button2中我读取了该值。如果我没有在按钮1中调用retain,那么当我单击button2时,该变量将被释放并且应用程序挂起,添加一个调用keep以使一切正常。

这是在OSX上使用带有firemonkey的Delphi XE6。

这里有一些代码

定义NSNumber

类型的表单变量
Fv : NSNumber;

现在添加几个按钮

用于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;

for Button2click

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而没有保留,则它会崩溃。

我应该保留 - 我不认为这是必要的,还是我错过了其他的东西?

TIA

1 个答案:

答案 0 :(得分:2)

感谢@RudyVelthius和@RemyLebeau让我走上了正确的道路。

问题不在于德尔福问题,而是客观的C问题(至少我对目标C的理解是问题)。

TNSNumber.OCClass.numberWithFloat(4.0)

是一个便利构造函数 - 这意味着它被添加到自动释放池中,并在下次主运行循环执行时释放。

所以我的delphi接口很好,但不幸的是它指向不再存在的东西。保持呼叫保留的自动释放变量。只是为了证明这是调用alloc / init应该修复它的问题。所以

替换

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

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

并删除保留,一切正常。

从这里https://stackoverflow.com/a/801000/416047规则是

  

如果返回对象的选择器有单词" new"," alloc",   "保留"或"复制"在它,然后你拥有返回的对象,并且   负责在你完成后释放它。

     

否则你不拥有它,不应该释放它。如果你想   保持对非拥有对象的引用,你应该调用 - [NSObject   保留]在那个实例上。你现在"拥有"那个例子是必须的   因此,当你完成时,在实例上调用 - [NSObject release]   用它。因此,您不拥有 - [NSNumber。]返回的实例   numberWithInt:]并且在完成后不应该调用-release。   如果要将返回的实例保持在当前范围之外   (真正超出当前NSAutoreleasePool的生命周期   例如,你应该 - 保持它。