[英]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.