iOS objective-c对象:何时使用版本和何时不使用版本

iOS objective-c对象:何时使用版本和何时不使用版本,ios,delphi,firemonkey,Ios,Delphi,Firemonkey,我在iOS下,我在delphi Tokyo开发,这是我的代码: aUIImage := TUIImage.Wrap(TUIImage.alloc.initWithCGImage(aCGImageRef)); try aData := TNSData.Wrap(UIImageJPEGRepresentation((aUIImage as ILocalObject).GetObjectID, cWin_DefaultJPGCompressionRate /

我在iOS下,我在delphi Tokyo开发,这是我的代码:

      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;
aUIImage:=TUIImage.Wrap(TUIImage.alloc.initWithCGImage(aCGImageRef));
尝试
aData:=TNSData.Wrap(UIImageJPEGRepresentation((aUIImage作为ILocalObject.GetObjectID,cWin_DefaultJPGCompressionRate/100));
尝试
aWorkPicStream.WriteBuffer(aData.bytes^,aData.length);
最后
aData.release;//地址0000000 184D4891C处的访问冲突,访问地址0000000 107FD286C
地址:$0000000 184D4891C(objc_msgSend+28)
调用堆栈:
myproj$0000000 103E00548 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*)+196
myproj$0000000 1030DF0EC Sysutils.Exception.RaisingException(TExceptionRecord*)+88
myproj$0000000 103116164 Sysutils.RaiseExceptObject(TExceptionRecord*)+84
myproj$0000000 1030BB498_raiseateExcept(TObject*,指针)+128
myproj$0000000 1030DD900内部执行信号转换器(NativeUInt,NativeUInt,NativeUInt)+68
libobjc.A.dylib$0000000 184d5213c+844
CoreFoundation$0000000 185A40AAC\u CFAutoreleasePoolPop+28
基金会0000000美元1864 FB960 + 148
myproj$0000000 1031B426c Classes.ThreadProc(Classes.TThread*)+948
myproj$00000
如果我注释行
aData.release那么我不会遇到任何错误


为什么??如何知道何时必须调用release,何时不能调用release?

iOS的ARC规则非常简单,如中所述

名称以
alloc
new
copy
mutableCopy
开头的方法不需要调用
retain
。相反,如果调用它,则会造成内存泄漏,因为将有一个
retain
太多。但它们确实需要
释放
自动释放
。这些对象实例就是您创建的对象实例,在Objective-C下,它们在构建时会自动保留

aUIImage
是使用
alloc
构建的,您拥有它,并负责使用
release
发布它。另一方面,您不拥有
aData
,它将由系统处理

要记住的另一件事是,对于您不拥有的对象,您可能需要调用
retain
release
,以保持对象实例在使用期间处于活动状态。由于接收到的对象通常保证在接收它的方法中保持有效,因此您不必在代码中调用
aData
时调用
retain
release


retainCount
方法返回Objective-C对象实例的当前引用计数。这个数字纯粹是信息性的,在iOS或macOS下没有调试价值,但是它足以显示Objective-C和Delphi内存管理之间的交互,有时会有所帮助

从Apple文档中可以看到:

重新计数
-不要使用此方法

此方法在调试内存管理问题时没有任何价值。 因为任何数量的框架对象都可能在中保留了一个对象 以保留对它的引用,同时自动释放 池可以在一个对象上保存任意数量的延迟发布,它 您不太可能从该方法中获得有用的信息


除了上述规则外,对于一般调试,您可以对目标运行静态分析——“Cmnd+Shift+B(构建)”。这将为可能的内存泄漏提供一些见解。(注意:在某些情况下,可能会说某个对象可能存在内存泄漏,但该对象可能会在代码中的其他地方释放。这取决于您的实现)

@RudyVelthuis Ok,但以这种方式,为什么aUIImage.release;没有提出任何错误吗?@RudyVelthuis:原始文档没有说任何不幸的事情:(
myproj  [E][W][I][D][V] Error => Access violation at address 0000000184D4891C, accessing address 0000000107FD286C
At address: $0000000184D4891C (objc_msgSend + 28)

Call stack:
myproj                    $0000000103E00548 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*) + 196
myproj                    $00000001030DF0EC Sysutils.Exception.RaisingException(TExceptionRecord*) + 88
myproj                    $0000000103116164 Sysutils.RaiseExceptObject(TExceptionRecord*) + 84
myproj                    $00000001030BB498 _RaiseAtExcept(TObject*, Pointer) + 128
myproj                    $00000001030DD900 Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt) + 68
libobjc.A.dylib           $0000000184D5213C <redacted> + 844
CoreFoundation            $0000000185A40AAC _CFAutoreleasePoolPop + 28
Foundation                $00000001864FB960 <redacted> + 148
myproj                    $00000001031B426C Classes.ThreadProc(Classes.TThread*) + 948
myproj                    $00000