gpt4 book ai didi

ios - 为什么我们需要对 Objective-C 对象字段进行保留?

转载 作者:行者123 更新时间:2023-12-02 01:53:44 29 4
gpt4 key购买 nike

这是Delphi媒体播放器的代码:

type
TAVMedia = class(TMedia)
private
FPlayer: AVPlayer;
FPlayerItem: AVPlayerItem;
public
constructor Create(const AFileName: string); override;
destructor Destroy; override;
end;

constructor TAVMedia.Create(const AFileName: string);
var aURL: NSUrl;
begin
inherited Create(AFileName);
FPlayerItem := TAVPlayerItem.Wrap(TAVPlayerItem.OCClass.playerItemWithURL(URL));
FPlayerItem.retain;
FPlayer := TAVPlayer.Wrap(TAVPlayer.OCClass.playerWithPlayerItem(FPlayerItem));
FPlayer.retain;
end;

destructor TAVMedia.Destroy;
begin
FPlayer.release;
FPlayer := nil;
FPlayerItem.release;
FPlayerItem := nil;
inherited Destroy;
end;

我不太明白为什么他们需要执行FPlayerItem.retainFPlayer.retainFPlayerItemFPlayer 是对象字段而不是局部变量,因此始终对它们有强引用。那么这里retain的目的是什么?

似乎执行FPlayer.release;也会释放FPlayerItem,因此当稍后调用FPlayerItem.release;时有时会触发访问冲突(奇怪的是并不总是)。

注意:我仍然不明白为什么我有 eaccessviolation,所以我决定将我所做的完整代码放在这里:

type
TMyMedia = class(TObject)
private
FPlayer: AVPlayer;
FPlayerItem: AVPlayerItem;
public
constructor Create;
destructor Destroy; override;
end;

constructor TMyMedia.Create;
begin
inherited Create;

P := TNSUrl.OCClass.URLWithString(StrToNSStr(aDataSource)); // Creates and returns an NSURL object initialized with a provided URL string
if P = nil then raise EFileNotFoundException.Create(SFileNotFound); // If the URL string was malformed or nil, returns nil.
aURL := TNSUrl.Wrap(P);
try

FPlayerItem := TAVPlayerItem.Wrap(TAVPlayerItem.OCClass.playerItemWithURL(URL));
FPlayerItem.retain;

finally
aURL.release; // << if i don't do this then i will not have any exception at the end ???
aURL := nil; // <<
end;


FPlayer := TAVPlayer.Wrap(TAVPlayer.OCClass.playerWithPlayerItem(FPlayerItem));
FPlayer.retain;
end;

destructor TAVMedia.Destroy;
begin

ALLog('FPlayer.retainCount', inttostr(FPlayer.retainCount)); // => show 1
ALLog('FPlayerItem.retainCount', inttostr(FPlayerItem.retainCount)); // => show 6

FPlayer.release;
FPlayer := nil;

ALLog('FPlayerItem.retainCount', inttostr(FPlayerItem.retainCount)); // => show 1
FPlayerItem.release; => here i receive Access violation at address 2156565 accessing address 68684458

FPlayerItem := nil;
inherited Destroy;
end;

最佳答案

TNSUrl.OCClass.URLWithStringTAVPlayerItem.OCClass.playerItemWithURL 将项目添加到自动释放池中。因此,保留计数为 1。当自动释放池释放其包含的项目时,它们将被释放,这通常发生在当前事件执行完成之后。

因此需要FPlayerItem.retain,因为函数退出后FPlayerItem不应该被释放。它已分配给 FPlayerItem,因此您希望使其保持事件状态。

一般来说,如果你用CreatealloccopymutableCopynew... 然后为您调用retain。然后你需要调用releaseautorelease

如果您使用其他函数(例如 fileUrlWithPath)创建这样的类,那么它将添加到自动释放池中。您的保留计数仍然为 1,但它将为您释放。如果你也释放它,那么你就会崩溃。

如果您在类上调用 retain,则该调用必须与 release 保持平衡。

关于ios - 为什么我们需要对 Objective-C 对象字段进行保留?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42222508/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com