Ich mache eine App, die Audio wiedergibt und ich habe es eingerichtet, so dass der Sperrbildschirm über MPNowPlayingInfoCenter
aktualisiert wird, aber ich habe ein Problem festgestellt.MPNowPlayingInfoCenter werfen EXC_BAD_ACCESS
Zu scheinbar zufälligen Zeiten, bekomme ich eine EXC_BAD_ACCESS
Fehler beim Versuch, die jetzt spielen Informationen zu aktualisieren.
Hier ist der Code, der so tut:
- (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% der Zeit, dies funktioniert, aber manchmal, wenn die App in den Hintergrund resignieren oder wenn Audiodateien ändern oder nur zufällig,
[npInfoCenter setNowPlayingInfo:_activeMetadata];
wirft EXC_BAD_ACCESS
.
Auch wird _activeMetadata
erklärt wie:
@property (atomic, strong, retain) NSMutableDictionary* activeMetadata;
Es instanziiert wird, wenn die AVPlayer erstellt:
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
wird über einen CADisplayLink auf jedem Frame genannt.
Irgendwelche Ideen, was die Ausnahme verursachen könnte?
Ich denke, du hast Recht. Ich denke, dass ich einen Fehler bekommen habe, weil ich den Inhalt von '_activeMetadata' zu häufig geändert habe und es wurde überschrieben, während es in das gerade spielende Zentrum kopiert wurde. Das Frame-Aktualisierungsintervall auf 2 fps anstelle von 60 fps zu reduzieren und eine Kopie des NSDictionary zu erstellen, bevor es den jetzt spielenden Informationen zugewiesen wird, scheint das Problem behoben zu haben. Seitdem habe ich keinen Unfall gehabt. – David
Ich stimme dir zu, dass es nicht gut ist, es so oft zu nennen. Aber ich denke, es sollte nicht abstürzen, nur weil es sehr häufig aufgerufen wird. Ich bin auf das gleiche Problem gestoßen, wenn ich Tracks zu schnell gewechselt habe. Erstellen Sie eine Kopie des Wörterbuchs, bevor Sie es für mich repariert haben. Danke. – d4Rk
@ d4Rk Eine Kopie des Wörterbuchs erstellen, bevor es repariert wurde? Ich bin immer noch stecken –