Dies ist der Code des Delphi-Media-Player:Warum müssen wir Objective-C-Objektfeld beibehalten?
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;
Ich verstehe nicht ganz, warum sie FPlayerItem.retain
und FPlayer.retain
tun müssen? FPlayerItem
und FPlayer
sind Objektfelder und keine lokalen Variablen, daher gibt es immer einen starken Bezug zu ihnen. Also, was ist der Zweck der retain
hier?
Es scheint, dass tun FPlayer.release;
wird auch die FPlayerItem
freigeben, so wenn später aufgerufen wird manchmal löst es Zugriffsverletzung (seltsamerweise nicht immer).
Hinweis: Ich kann immer noch nicht verstehen, warum ich eine EAccessViolation haben, so habe ich beschlossen, hier den vollständigen Code genau zu setzen, was ich tat:
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;
Dank Dalija, verstehe ich jetzt sehr gut das notwendige Ruf zu behalten. aber diese Ausnahme macht mich verrückt. Kurz bevor ich FPlayerItem.release tue, drucke ich FPlayerItem.retainCount und es wird angezeigt 1. aber sobald ich FPlayerItem.release habe, habe ich einen eAccessViolation :( –
Hast du Callbacks oder Threads? Wenn 'FPlayerItem' nach dir auf Null gesetzt ist Rufen Sie 'FPlayerItem.release' auf, die' FPlayerItem' Wrapper-Objekt verwenden können, das jetzt nicht mehr existierende Objective-C-Instanz verwendet. –
Nichts, ich entferne alles (alle Delegaten, etc), um den Code so einfach wie möglich zu machen Diese Frage, um Ihnen den vollen Code zu zeigen, kann ich nicht verstehen ... –