iOS objective-c object:什么时候用release,什么时候不用
iOS objective-c object: When to use release and when to not use it
我在 iOS 下,我在 delphi 东京开发,这是我的代码:
aUIImage := TUIImage.Wrap(TUIImage.alloc.initWithCGImage(aCGImageRef));
try
aData := TNSData.Wrap(UIImageJPEGRepresentation((aUIImage as ILocalObject).GetObjectID, cWin_DefaultJPGCompressionRate / 100));
try
aWorkPicStream.WriteBuffer(aData.bytes^, aData.length);
finally
aData.release; // << this make my code will crash (later not now)
end;
finally
aUIImage.release;
end;
在执行之前的代码之后,我稍晚一点在执行这个错误:
myproj [E][W][I][D][V] Error => Access violation at address 0000000184D4891C, accessing address 0000000107FD286C
At address: [=13=]00000184D4891C (objc_msgSend + 28)
Call stack:
myproj [=13=]00000103E00548 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*) + 196
myproj [=13=]000001030DF0EC Sysutils.Exception.RaisingException(TExceptionRecord*) + 88
myproj [=13=]00000103116164 Sysutils.RaiseExceptObject(TExceptionRecord*) + 84
myproj [=13=]000001030BB498 _RaiseAtExcept(TObject*, Pointer) + 128
myproj [=13=]000001030DD900 Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt) + 68
libobjc.A.dylib [=13=]00000184D5213C <redacted> + 844
CoreFoundation [=13=]00000185A40AAC _CFAutoreleasePoolPop + 28
Foundation [=13=]000001864FB960 <redacted> + 148
myproj [=13=]000001031B426C Classes.ThreadProc(Classes.TThread*) + 948
myproj [=13=]000
如果我注释行 aData.release;
那么我将不会遇到任何错误。
为什么?如何知道什么时候必须调用 release 什么时候不能调用 release ?
iOS 的 ARC 规则非常简单,如 Apple's Basic Memory Management Rules 中所述。
名称以 alloc
、new
、copy
或 mutableCopy
开头的方法不需要调用 retain
。相反,如果调用它,则会造成内存泄漏,因为 retain
太多了。但它们确实需要 release
或 autorelease
。这些对象实例是您创建的实例,在 Objective-C 下,它们在构造时会自动保留。
aUIImage
是用alloc
构造的,你拥有它,你负责用release
释放它。另一方面,您不拥有 aData
,它将由系统处理。
另一件要记住的事情是,对于您不拥有的对象,您可能需要同时调用 retain
和 release
以在您使用时保持对象实例处于活动状态它。由于接收到的对象通常保证在接收到它的方法中保持有效,因此您不必在代码中的 aData
上调用 retain
和 release
。
retainCount
方法 returns Objective-C 对象实例的当前引用计数。这个数字纯粹是信息性的,在 iOS 或 macOS 下没有调试价值,但是它足以显示 Objective-C 和 Delphi 内存管理之间的交互,有时会有帮助。
来自关于 retainCount 的 Apple 文档:
retainCount
- Do not use this method
This method is of no value in debugging memory management issues.
Because any number of framework objects may have retained an object in
order to hold references to it, while at the same time autorelease
pools may be holding any number of deferred releases on an object, it
is very unlikely that you can get useful information from this method.
除上述规则外,对于一般调试,您可以运行 对目标进行静态分析 - "Cmnd+Shift+B(Build)"。这将对可能的内存泄漏提供一些见解。 (注意:在某些情况下,它可能会说某个对象可能存在内存泄漏,但该对象可能会在代码中的其他地方释放。这取决于您的实现)
我在 iOS 下,我在 delphi 东京开发,这是我的代码:
aUIImage := TUIImage.Wrap(TUIImage.alloc.initWithCGImage(aCGImageRef));
try
aData := TNSData.Wrap(UIImageJPEGRepresentation((aUIImage as ILocalObject).GetObjectID, cWin_DefaultJPGCompressionRate / 100));
try
aWorkPicStream.WriteBuffer(aData.bytes^, aData.length);
finally
aData.release; // << this make my code will crash (later not now)
end;
finally
aUIImage.release;
end;
在执行之前的代码之后,我稍晚一点在执行这个错误:
myproj [E][W][I][D][V] Error => Access violation at address 0000000184D4891C, accessing address 0000000107FD286C
At address: [=13=]00000184D4891C (objc_msgSend + 28)
Call stack:
myproj [=13=]00000103E00548 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*) + 196
myproj [=13=]000001030DF0EC Sysutils.Exception.RaisingException(TExceptionRecord*) + 88
myproj [=13=]00000103116164 Sysutils.RaiseExceptObject(TExceptionRecord*) + 84
myproj [=13=]000001030BB498 _RaiseAtExcept(TObject*, Pointer) + 128
myproj [=13=]000001030DD900 Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt) + 68
libobjc.A.dylib [=13=]00000184D5213C <redacted> + 844
CoreFoundation [=13=]00000185A40AAC _CFAutoreleasePoolPop + 28
Foundation [=13=]000001864FB960 <redacted> + 148
myproj [=13=]000001031B426C Classes.ThreadProc(Classes.TThread*) + 948
myproj [=13=]000
如果我注释行 aData.release;
那么我将不会遇到任何错误。
为什么?如何知道什么时候必须调用 release 什么时候不能调用 release ?
iOS 的 ARC 规则非常简单,如 Apple's Basic Memory Management Rules 中所述。
名称以 alloc
、new
、copy
或 mutableCopy
开头的方法不需要调用 retain
。相反,如果调用它,则会造成内存泄漏,因为 retain
太多了。但它们确实需要 release
或 autorelease
。这些对象实例是您创建的实例,在 Objective-C 下,它们在构造时会自动保留。
aUIImage
是用alloc
构造的,你拥有它,你负责用release
释放它。另一方面,您不拥有 aData
,它将由系统处理。
另一件要记住的事情是,对于您不拥有的对象,您可能需要同时调用 retain
和 release
以在您使用时保持对象实例处于活动状态它。由于接收到的对象通常保证在接收到它的方法中保持有效,因此您不必在代码中的 aData
上调用 retain
和 release
。
retainCount
方法 returns Objective-C 对象实例的当前引用计数。这个数字纯粹是信息性的,在 iOS 或 macOS 下没有调试价值,但是它足以显示 Objective-C 和 Delphi 内存管理之间的交互,有时会有帮助。
来自关于 retainCount 的 Apple 文档:
retainCount
- Do not use this methodThis method is of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.
除上述规则外,对于一般调试,您可以运行 对目标进行静态分析 - "Cmnd+Shift+B(Build)"。这将对可能的内存泄漏提供一些见解。 (注意:在某些情况下,它可能会说某个对象可能存在内存泄漏,但该对象可能会在代码中的其他地方释放。这取决于您的实现)