Как найти конкретный ключ / значение (список свойств) - PullRequest
2 голосов
/ 23 мая 2010

я учу какао / цель-с. Прямо сейчас я имею дело с кодированием ключ / значение. Прочитав книгу Аарона и другие источники, я подумал, что смог оставить простые примеры и попробовать сложные ...

Я пытаюсь прочитать список свойств 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>

Как видите, списки воспроизведения хранятся в виде словарей внутри массива, а ключ, который его идентифицирует, находится внутри него, а не как <key> перед ним.

Проблема в том, что я не могу понять, как искать ключ, находящийся внутри другого.

С помощью следующего кода я могу найти массив, в котором хранятся списки воспроизведения, но как найти конкретный <dict>? В приведенном выше списке словарь имеет 3 ключа для его идентификации: имя, мастер и идентификатор. Первый плейлист имеет идентификатор 20117 и второй 45013. Как получить треки плейлиста 20117?

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

Здесь, в Stackoverflow, я нашел эту запись , но я не уверен, что итерация по массиву и проверка это хорошая идея.

Я совершенно уверен, что смогу использовать valueForKeyPath, но я не могу понять, как это сделать.

Любая помощь приветствуется.

ТИА

Bob

Ответы [ 3 ]

2 голосов
/ 30 мая 2010

Предположим, вы хотите найти «Идентификатор списка воспроизведения» == 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"]);
}

Обратите внимание, что быстрое перечисление в этом случае вернет только одну запись (если есть)

0 голосов
/ 23 мая 2010

Как выясняется, NSFastEnumeration (тот, где вы говорите for (NSDictionary *playlist in Playlists), вполне, хорошо, быстро. Подробности смотрите здесь . Если по какой-то сумасшедшей причине вы действительно понимаете если вы не хотите этого делать, вы можете использовать - (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate, но это, вероятно, в любом случае перебирает массив. Материал NSPredicate был более или менее спроектирован для обработки такого типа вещей, но они сбивают с толку и ограничены. быстро, потому что, за исключением оптимизации больших стилей базы данных, фильтрационные абстракции обычно заканчиваются итерациями в любом случае (теряя эффективность, заставляя вас создавать + уничтожать + взаимодействовать с различными объектами).

0 голосов
/ 23 мая 2010

см. -propertyList метод NSString.

...