【问题标题】:How to find an specific key/value (property list)如何查找特定的键/值(属性列表)
【发布时间】:2010-05-22 23:42:21
【问题描述】:

我正在学习 cocoa/objective-c。现在我正在处理键/值编码。在阅读了 Aaron 的书和其他资料后,我认为我可以离开简单的例子,尝试一个复杂的例子......

我正在尝试读取 iTunes 属性列表 (iTunes Music Library.xml)。我想检索特定播放列表中的曲目。

可能每个人都知道,但下面我放了一段xml:

<plist version="1.0">
<dict>
   <key>Major Version</key><integer>1</integer>
   ...
   <key>Playlists</key>
   <array>
      <dict>
         <key>Name</key><string>Library</string>
         <key>Master</key><true/>
         <key>Playlist ID</key><integer>20117</integer>
         ...
         <key>Playlist Items</key>
         <array>
            <dict>
               <key>Track ID</key><integer>10281</integer>
            </dict>
            <dict>
               <key>Track ID</key><integer>10283</integer>
            </dict>
            <dict>
               <key>Track ID</key><integer>10285</integer>
            </dict>
            ...
         </array>
      </dict>
      <dict>
         <key>Name</key><string>Classical Music</string>
         <key>Playlist ID</key><integer>45013</integer>
         ...
      </dict>
   </array>
</dict>
</plist>

如您所见,播放列表作为字典存储在数组中,标识它的键在其中,而不是前面的 &lt;key&gt;

问题是我无法弄清楚如何搜索另一个密钥中的密钥。

通过以下代码,我可以找到存储播放列表的数组,但是如何找到特定的&lt;dict&gt;?在上面的 plist 中,字典有 3 个键来识别它:name、master 和 id。第一个播放列表的id为20117,第二个为45013。如何获取播放列表20117的曲目?

NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:file];
NSArray *playlists = [rootDict objectForKey:@"Playlists"];

我在 Stackoverflow 找到了这个 post,但我不确定迭代数组并测试它是否是个好主意。

我很确定我可以使用valueForKeyPath,但我不知道该怎么做。

欢迎任何帮助。

TIA,

鲍勃

【问题讨论】:

  • 你想找到第一个包含给定轨道 id 的字典吗?
  • 否,按播放列表名称或其他键。我将编辑我的帖子以添加播放列表字典中的其他键。

标签: objective-c itunes plist


【解决方案1】:

假设您要搜索“播放列表 ID”== 12194:

NSString *path = [[NSBundle mainBundle] pathForResource:@"iTunes Music Library" ofType:@"xml"];
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *playlists = [rootDict objectForKey:@"Playlists"];

NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K == %@", @"Playlist ID", 
                          [NSNumber numberWithInt:12194]];
NSArray *filteredArray = [playlists filteredArrayUsingPredicate:pred];

for (NSDictionary *dict in filteredArray) {
     NSLog(@"Name = %@", [dict valueForKey:@"Name"]);
     NSLog(@"Playlist ID = %@", [dict valueForKey:@"Playlist ID"]);
}

注意快速枚举,在这种情况下,只会返回一条记录(如果有的话)

【讨论】:

    【解决方案2】:

    事实证明,NSFastEnumeration(你所说的 for (NSDictionary *playlist in Playlists) 相当、好、很快。有关详细信息,请参阅 here。如果出于某种疯狂的原因你真的不想要为此,您可以使用- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate,但这可能会遍历数组。NSPredicate 的东西或多或少被设计为处理这种类型的事情,但它们令人困惑和有限。基本上迭代事情真的很快,因为除非进行大型数据库样式优化,否则过滤抽象通常最终还是会迭代(通过让您构造+销毁+与各种对象的接口来浪费效率)。

    【讨论】:

      【解决方案3】:

      参见NSString-propertyList 方法。

      【讨论】:

        猜你喜欢
        • 2013-09-27
        • 2011-11-09
        • 2021-05-19
        • 2016-04-03
        • 1970-01-01
        • 2020-06-11
        • 2012-12-12
        • 2021-09-09
        相关资源
        最近更新 更多