2016-09-18 6 views
2

Я создаю приложение, воспроизводящее аудио, и я настроил его так, чтобы экран блокировки обновлялся через 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 на каждом кадре.

Любые идеи, которые могут вызывать исключение?

ответ

2

Я думаю, что вы слишком часто вызываете setNowPlayingInfo. Конечно, это действительно не должно терпеть крах, но нет необходимости использовать CADisplayLink, чтобы называть его 60 раз в секунду.

Так почему вы так часто называете это? Если это происходит из-за того, что вы хотите прогрессировать, чтобы отслеживать плавный ход, по-прежнему нет необходимости. Из заявления MPNowPlayingInfoPropertyElapsedPlaybackTime:

// The elapsed time of the now playing item, in seconds. 
// Note the elapsed time will be automatically extrapolated from the previously 
// provided elapsed time and playback rate, so updating this property frequently 
// is not required (or recommended.) 

p.s. Я попробовал код с файлом m4a и нашел, что durInterval был NotNumber. С правильной продолжительностью и вызовом setNowPlayingInfo только один раз индикатор выполнения отслеживал штраф & ничего не разбилось.

+0

Я думаю, что вы правы. Я думаю, что у меня была ошибка, потому что я слишком часто менял содержимое '_activeMetadata', и он был перезаписан во время копирования в текущий игровой центр. Уменьшение интервала обновления фрейма до 2fps вместо 60fps и создание копии NSDictionary перед назначением его текущей информации, похоже, устранили проблему. С тех пор у меня не было крушения. – David

+0

Я согласен с вами, что это нехорошо называть это так часто. Но я думаю, что он не должен терпеть крах, просто потому, что он называется очень часто. Я столкнулся с тем же вопросом, слишком быстро переключая дорожки. Сделав копию Словаря, прежде чем установить его для меня. Спасибо. – d4Rk

+0

@ d4Rk Создание копии словаря до исправления? Im все еще застрял –

 Смежные вопросы

  • Нет связанных вопросов^_^