Это код медиаплеера Delphi:Зачем нам нужно сохранять для объекта Objective-C?
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.retain
и FPlayer.retain
? FPlayerItem
и FPlayer
- это поля объектов, а не локальные переменные, поэтому для них всегда существует сильная ссылка. Итак, какова цель 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;
Спасибо, Далия, я понимаю, что сейчас очень хорошо нужно позвонить. но это исключение делает меня сумасшедшим. перед тем, как делать FPlayerItem.release, я распечатаю FPlayerItem.retainCount, и это шоу 1. но как только я сделаю FPlayerItem.release, у меня есть eaccessViolation :( –
Есть ли у вас какие-либо обратные вызовы или потоки? Если 'FPlayerItem' установлен на нуль после вас вызовите 'FPlayerItem.release', которые могут использовать объект-оболочку' FPlayerItem', который использует теперь уже не существующий экземпляр Objective-C. –
ничего, я удаляю все (все делегаты и т. д.), чтобы сделать код максимально простым. этот вопрос, чтобы показать вам полный код. Я не могу понять ... –