Я создаю приложение, воспроизводящее аудио, и я настроил его так, чтобы экран блокировки обновлялся через MPNowPlayingInfoCenter
, но у меня возникла проблема.MPNowPlayingInfoCenter throwing EXC_BAD_ACCESS
При каждых случайных временах я получаю ошибку EXC_BAD_ACCESS
при попытке обновить информацию, воспроизводящуюся сейчас.
Вот код, который делает так:
- (void)updatePlayback
{
if(!active)
return;
NowPlayingController* npc = [AudioController nowPlayingController];
CMTime elapsed = player.currentTime;
Float64 elInterval = CMTimeGetSeconds(elapsed);
[npc setElapsed:elInterval];
CMTime duration = player.currentItem.duration;
Float64 durInterval = CMTimeGetSeconds(duration);
[npc setRemaining:ceilf(durInterval - elInterval)];
[npc setPlayPauseValue:isPlaying];
if(durInterval > 0)
{
[npc setProgressValue:elInterval/durInterval];
[npc setAudioDuration:durInterval];
}
_activeMetadata[MPMediaItemPropertyPlaybackDuration] = @(durInterval);
_activeMetadata[MPNowPlayingInfoPropertyPlaybackRate] = @(isPlaying);
_activeMetadata[MPNowPlayingInfoPropertyElapsedPlaybackTime] = @(elInterval);
MPNowPlayingInfoCenter* npInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
if(npInfoCenter && _activeMetadata)
{
if([npInfoCenter respondsToSelector:@selector(setNowPlayingInfo:)])
{
//////////THE FOLLOWING LINE TRIGGERS EXC_BAD_ACCESS SOMETIMES////////////
[npInfoCenter setNowPlayingInfo:_activeMetadata];
}
}
}
99,9% времени, это работает, но иногда, когда в отставку приложение на фоне или при смене аудио файлов, или просто случайно,
[npInfoCenter setNowPlayingInfo:_activeMetadata];
throws EXC_BAD_ACCESS
.
Кроме того, _activeMetadata
объявлен как:
@property (atomic, strong, retain) NSMutableDictionary* activeMetadata;
Он конкретизируется, когда AVPlayer создается:
AVAsset* asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:path]];
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:asset];
player = [AVPlayer playerWithPlayerItem:playerItem];
CMTime duration = player.currentItem.duration;
NSTimeInterval durInterval = CMTimeGetSeconds(duration);
NSLog(@"%f", durInterval);
MPMediaItemArtwork* albumArtwork = [[MPMediaItemArtwork alloc] initWithImage:[downloader useCachedImage:CacheKeySeriesBanners withName:nil withURL:info[@"image"]]];
NSDictionary* nowPlayingInfo = @{MPMediaItemPropertyTitle:ptString,
MPMediaItemPropertyArtist:spString,
MPMediaItemPropertyArtwork:albumArtwork,
MPMediaItemPropertyAlbumTitle:info[@"title"],
MPMediaItemPropertyPlaybackDuration:@(durInterval),
MPNowPlayingInfoPropertyPlaybackRate:@(1),
MPNowPlayingInfoPropertyElapsedPlaybackTime:@(0)};
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:nowPlayingInfo];
_activeMetadata = [nowPlayingInfo mutableCopy];
updatePlayback
вызывается через CADisplayLink на каждом кадре.
Любые идеи, которые могут вызывать исключение?
Я думаю, что вы правы. Я думаю, что у меня была ошибка, потому что я слишком часто менял содержимое '_activeMetadata', и он был перезаписан во время копирования в текущий игровой центр. Уменьшение интервала обновления фрейма до 2fps вместо 60fps и создание копии NSDictionary перед назначением его текущей информации, похоже, устранили проблему. С тех пор у меня не было крушения. – David
Я согласен с вами, что это нехорошо называть это так часто. Но я думаю, что он не должен терпеть крах, просто потому, что он называется очень часто. Я столкнулся с тем же вопросом, слишком быстро переключая дорожки. Сделав копию Словаря, прежде чем установить его для меня. Спасибо. – d4Rk
@ d4Rk Создание копии словаря до исправления? Im все еще застрял –