0

我正在构建一个音乐应用程序,我正在尝试使用这段代码获取 MP3 文件元数据:

for (NSString *format in [assest availableMetadataFormats]) {

        for (AVMetadataItem *item in [assest metadataForFormat:format]) {
            if ([[item commonKey] isEqualToString:@"title"]) {

                [SongNameMutableArray addObject:[NSString stringWithFormat:@"%@",[item value]]];
            }
            if ([[item commonKey] isEqualToString:@"artist"]) {

                [ArtistMutableArray addObject:[NSString stringWithFormat:@"%@",[item value]]];
            }
            if ([[item commonKey] isEqualToString:@"albumName"]) {

            }
            if ([[item commonKey] isEqualToString:@"artwork"]) {
                UIImage *img = nil;
                if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) {
                    img = [UIImage imageWithData:item.dataValue];

                }
                else {
                    NSDictionary *dict ;
                    [item.value copyWithZone:nil];
                    img = [UIImage imageWithData:[dict objectForKey:@"data"]];

                }
            }
        }
    }

代码工作正常。唯一的问题是,当可变数组被填充时,它们以下列方式进行:

  • SongNameMutableArray => [song1, song2, song3, songX];
  • ArtistMutableArray => [Artists1, Artist3, Artist 10, ArtistX];

因为并非所有歌曲的元数据中都有艺术家。

根据代码的这个特定部分

if ([[item commonKey] isEqualToString:@"artist"]) {
    [ArtistMutableArray addObject:[NSString stringWithFormat:@"%@",[item value]]];
}

如果找到的项目是艺术家,则将其插入数组中。

现在我的问题是如何检测一首歌曲何时在元数据中没有艺术家?这样我就可以在 ArtistMutableArray => [Artists1, null, Artist3, null, Artist 5, ArtistX] 中插入“null”;

我试过:

if ([[item commonKey] isEqualToString:@"null"])
if ([[item value] isEqualToString:@"null"])

我不确定我在这里缺少什么。

4

1 回答 1

0

您所做的一切都需要以不同的方式进行。不要将数据拆分为单独的数组,特别是如果您希望每个数组具有相同数量的元素并且每个对应的索引都引用相同的资产。

相反,定义一个包含您要为每个资产跟踪的少数属性的类。然后有一个这些类实例的数组。然后无需担心保持多个数组同步并通过在需要的地方向数组添加“null”值来执行技巧。

拥有一组数据还有许多其他好处。例如,排序。例如,通过拥有一个数组,您可以按艺术家对一组数据进行排序。在排序或过滤时试图使多个数组保持同步是一个巨大的痛苦。

由于您获得的只是通用元数据,因此无需遍历所有格式并查看每种格式的属性。只需使用commonMetadata资产的属性。

获取commonKey值时,不要将其与硬编码字符串进行比较。使用 API 提供的常量,例如AVMetadataCommonKeyAlbumName.

并且由于每个元数据项只能有一个 的值commonKey,因此使用if/else它可以使您的代码更高效。并使用stringValue元数据项的属性来获取字符串值,而不是使用stringWithFormat.

这是您的元数据类的开始。命名您认为合适的名称并添加您需要的任何其他属性。

@interface MyMetaData: NSObject

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *artist;
@property (nonatomic, copy) NSString *albumName;
@property (nonatomic, copy) UIImage *artwork;

@end

@implementation MyMetaData
@end

这是您在问题中发布的代码的替代品:

NSMutableArray *metadata = [NSMutableArray array]; // your array of obtained metadata

AVAsset *asset = // some asset

MyMetaData *data = [[MyMetaData alloc] init];

NSArray *commonData = asset.commonMetadata;
for (AVMetadataItem *item in commonData) {
    AVMetadataKey key = item.commonKey;
    if ([key isEqual: AVMetadataCommonKeyTitle]) {
        data.title = item.stringValue;
    } else if ([key isEqual:AVMetadataCommonKeyArtist]) {
        data.artist = item.stringValue;
    } else if ([key isEqual:AVMetadataCommonKeyAlbumName]) {
        data.albumName = item.stringValue;
    } else if ([key isEqual:AVMetadataCommonKeyArtwork]) {
        data.artwork = // your code to get the image
    }
}

[metadata addObject:data];

这要干净得多,您现在只需处理一个数组。如果给定资产没有数据,例如艺术家,那么该值只会保留nil在给定MyMetaData实例上。

于 2018-03-15T23:13:51.910 回答