views:

253

answers:

5

Hi,

I'm learning cocoa/objective-c. Right now I'm dealing with key/value coding. After reading Aaron's book and other sources, I thought that I was able to left the simple examples and try a complex one...

I'm trying read iTunes property list (iTunes Music Library.xml). I would like to retrieve the tracks held by an specific playlist.

Probably everybody knows it, but bellow I put a piece of the 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>

As you can see, the playlists are stored as dictionaries inside an array, and the key that identifies it is inside it, not as a <key> preceding it.

The problem is that I'm not able to figure out how to search for a key that is inside another one.

With the following code I can find the the array in which the playlists are stored, but how to find an specific <dict>? In above plist, the dictionary has 3 keys to identify it: name, master and id. The first playlist has the id 20117 and de second 45013. How to get the tracks of playlist 20117?

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

Here at Stackoverflow I found this post, but I'm not sure if iterate over the array and test it is a good idea.

I'm quite sure that I could use valueForKeyPath, but I'm unable to figure out how to do it.

Any help is welcome.

TIA,

Bob

A: 

see the -propertyList method of NSString.

NSResponder
A: 

As it turns out, NSFastEnumeration (the one where you say for (NSDictionary *playlist in Playlists) is quite, well, fast. See here for details. If for some crazy reason you really don't want to do that, you can use - (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate, but that probably iterates over the array anyway. NSPredicate stuff was more or less designed to handle this type of thing, but they are confusing and limited. Basically iterating over things is really fast, because barring large database style optimizations, filtering abstractions usually end up iterating anyway (wasting efficiency by making you construct+destroy+interface with various objects).

Jared P
+2  A: 

Supposing you want to search the "Playlist 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"]);
}

Note the fast enumeration, in this case, would return only one record (if any)

unixo
A: 

Hi !

I'm beginner and I try to understand... HOW I can make a request to show all data (from plist) in SAME category (NOT ALL !) for exemple : show only the movie have : genre = Action

Please help me ... Thanks a lot ! Excuse my bad english !

Is it in this code I must make it or an other ???

  • (id)initWithLibraryName:(NSString *)libraryName { if (self = [super init]) { libraryPlist = libraryName; libraryContent = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:libraryPlist ofType:@"plist"]];
Fraise
A: 

HOW I can make a request to show from data plist only one categoy for exemple : show for the movie : category = Action

you can download the source for help me on : http://www.iphonedevcentral.com/wp-content/uploads/2009/08/MyDVDLibrary03.zip PLEASE SAY ME HOW I CAN DO IT !

I will want to know the exact CODE LINE and WHERE I must write it ! For see a the list of product are in Action.

THANKS VERY VERY MUCH Are you near France ? for say to you : THANKS, I can send a product of my country if you help me for my appli and maybe more...

Fraise