繁体   English   中英

OSX上的Delphi XE6 ARC发布变量

[英]Delphi XE6 ARC on OSX releasing variables

当我没想到时,我遇到了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;

对于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

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

问题不是delphi问题,而是客观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”,“retain”或“copy”,那么您拥有返回的对象并负责在完成后释放它。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM