【问题标题】:MPNowPlayingInfoCenter throwing EXC_BAD_ACCESSMPNowPlayingInfoCenter 抛出 EXC_BAD_ACCESS
【发布时间】:2016-09-18 08:01:17
【问题描述】:

我正在制作一个播放音频的应用程序,并且我已经对其进行了设置,以便通过MPNowPlayingInfoCenter 更新锁定屏幕,但我遇到了问题。

在看似随机的时间,我在尝试更新正在播放的信息时收到 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

另外,_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 调用。

任何想法可能导致异常?

【问题讨论】:

    标签: ios objective-c avfoundation mpnowplayinginfocenter


    【解决方案1】:

    我觉得你打电话给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.)
    

    附言我用 m4a 文件尝试了代码,发现 durInterval 是 NotANumber。使用正确的持续时间并仅调用一次setNowPlayingInfo,进度条跟踪良好,没有任何崩溃。

    【讨论】:

    • 我认为你是对的。我认为我遇到了错误,因为我过于频繁地更改_activeMetadata 的内容,并且在复制到正在播放的中心时它被覆盖了。将帧更新间隔减少到 2fps 而不是 60fps 并在将其分配给正在播放的信息之前创建 NSDictionary 的副本似乎已经解决了这个问题。从那以后我再也没有发生过车祸。
    • 我同意你的观点,经常调用它是不好的。但我认为,它不应该崩溃,只是因为它被非常频繁地调用。我在切换曲目时遇到了同样的问题。在为我修复它之前制作字典的副本。谢谢。
    • @d4Rk 在修复之前制作字典的副本?我还是卡住了
    • @David 请举例说明..仍然卡住
    • @Kiraneldho 这个问题实际上在 Davids 的评论中得到了很好的描述。所以在你把它交给现在播放之前,只需创建一个字典的副本。
    【解决方案2】:

    Apple 在 iOS 10.3 及更高版本中修复了此崩溃问题。 因此,如果您想支持 iOS 10.2.1 及更低版本,请务必限制设置 [MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo 属性的频率。可能会限制每秒只设置一次属性。

    【讨论】:

      猜你喜欢
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多