2016-09-18 7 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]; 

EXC_BAD_ACCESS입니다.

@property (atomic, strong, retain) NSMutableDictionary* activeMetadata; 

가 인스턴스화되는 AVPlayer를 만들 때 :로

또한 _activeMetadata 선언된다

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은 NotANumber였습니다. 올바른 기간과 setNowPlayingInfo을 한 번만 호출하면 진행률 표시 줄이 미세하게 &을 추적합니다.

+0

나는 당신이 맞았다 고 생각합니다. 나는'_activeMetadata'의 내용을 너무 자주 변경했기 때문에 오류가 발생했다고 생각하고 현재 재생중인 센터로 복사되는 동안 덮어 쓰여지고있었습니다. 프레임 업데이트 간격을 60fps 대신 2fps로 줄이고 현재 재생중인 정보에 할당하기 전에 NSDictionary의 복사본을 만드는 것이 문제를 해결 한 것 같습니다. 그 이후로 나는 추락하지 않았다. – David

+0

자주 전화하는 것이 좋지 않다는 것에 동의합니다. 하지만 너무 자주 호출되기 때문에 충돌하지 않아야한다고 생각합니다. 트랙을 너무 빠르게 전환 할 때 같은 문제가 발생했습니다. 사전에 사본을 만들어서 저를 위해 고쳤습니다. 고마워. – d4Rk

+0

@ d4Rk 사전을 수정하기 전에 복사 하시겠습니까? 아직도 붙어있는 Im –