编辑:罪魁祸首是iOS 8,而不是模拟器(我没有意识到已经运行iOS 8),我已经更改了标题以反映这一点。
我曾经在我的iOS 7.1的iPhone 5上使用此SO问题中的代码来加载mp3文件中的专辑封面。
但后来,在iOS模拟器中发现了与这个代码有关的崩溃情况。进一步调查发现,这个代码也会使我的iPad崩溃。在将其升级到iOS 8之后,它会导致iPad崩溃。
看起来包含图像的字典已受损。
我创建了一个虚拟的iOS项目,其中仅加载专辑封面并得到了相同的结果。下面是来自该视图控制器的代码:
- (void) viewDidAppear:(BOOL)animated
{
self.titleText = @"Overkill"; // Set song filename here
NSString *filePath = [[NSBundle mainBundle] pathForResource:self.titleText ofType:@"mp3"];
if (!filePath) {
return;
}
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSLog(@"Getting song metadata for %@", self.titleText);
AVAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
if (asset != nil) {
NSArray *keys = [NSArray arrayWithObjects:@"commonMetadata", nil];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
NSArray *artworks = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata
withKey:AVMetadataCommonKeyArtwork
keySpace:AVMetadataKeySpaceCommon];
UIImage *albumArtWork;
for (AVMetadataItem *item in artworks) {
if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
NSDictionary *dict = [item.value copyWithZone:nil];
// **********
// Crashes here with SIGABRT. dict is not a valid dictionary.
// **********
if ([dict objectForKey:@"data"]) {
albumArtWork = [UIImage imageWithData:[dict objectForKey:@"data"]];
}
}
else if ([item.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
// This doesn't appear to get called for images set (ironically) in iTunes
albumArtWork = [UIImage imageWithData:[item.value copyWithZone:nil]];
}
}
if (albumArtWork != nil) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self.albumArtImageView setImage:albumArtWork];
});
}
}];
}
}
我已经标记了崩溃的那一行代码,它需要在捆绑包中有一个名为
Overkill.mp3
的文件。我用从iTunes和Amazon导出的多个mp3和m4a文件进行了测试,所以我知道这些文件本身是被正确编码的。在Xcode 6.0和6.1中进行了测试。
为什么它能在iPhone上工作,而不在模拟器或iPad上?有什么想法吗?
编辑/更新:
记录item.value后发现差异。
在iPhone 5上(有效):
(lldb) po item.value
{
MIME = JPG;
data = <ffd8ffe0 .... several Kb of data ..... 2a17ffd9>;
identifier = "";
picturetype = Other;
}
模拟器(崩溃)
(lldb) po item.value
<ffd8ffe0 .... several Kb of data ..... 2a17ffd9>
看起来模拟器上没有词典,只有原始艺术品。
将代码更改为不期望字典,而是将item.value
作为UIImage 可行!
for (AVMetadataItem *item in artworks) {
if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
NSData *newImage = [item.value copyWithZone:nil];
albumArtWork = [UIImage imageWithData:newImage];
}
...
}
item.value
、item
以及通过复制item.value
创建的字典。另外,请发布回溯和崩溃日志本身好吗? - duci9yAVMetadataID3MetadataKeyAttachedPicture
来处理MP3文件,使用AVMetadataiTunesMetadataKeyCoverArt
来处理iTunes文件,而不是常用的键,看看是否能获得更可预测的结果。 - duci9y