Today I continued reading the (e)book, and did the exercise 15.9, here's my solution. It wasn't very difficult, but it was a great to use some Obj-C again. I really like it, just need to learn it a bit (lot) better.
Here you go...
Song.h@interface Song : NSObject {
NSString *artist, *song;
}
@property (nonatomic, copy) NSString *song, *artist;
-(void)print;
-(void)dealloc;
-(id) initWithArtist: (NSString *)a andSong: (NSString *)s;
@end
Song.m#import "Song.h"
@implementation Song
@synthesize artist, song;
-(void)print
{
NSLog(@"%s - %s", [song UTF8String], [artist UTF8String]);
}
-(void)dealloc
{
[artist release];
[song release];
[super dealloc];
}
-(id) initWithArtist: (NSString *)a andSong: (NSString *)s
{
self = [super init];
[self setArtist: a];
[self setSong: s];
return self;
}
@end
PlayList.h#import "Song.h"
@interface PlayList : NSObject {
NSString * name;
NSMutableArray * songs;
}
@property (nonatomic, copy) NSString * name;
-(unsigned long) numberOfSongs;
-(NSMutableArray *) getSongs;
-(void) attachSong: (Song *) s;
-(void) detachSong: (Song *) s;
-(void)print;
-(void)search: (NSString *) searchFor;
-(void) dealloc;
-(id) initWithName: (NSString *) name;
@end
PlayList.m#import "PlayList.h"
@implementation PlayList
@synthesize name;
-(unsigned long) numberOfSongs
{
return [songs count];
}
-(NSMutableArray *) getSongs
{
return [songs copy];
}
-(void) attachSong: (Song *) s
{
if (!songs)
songs = [[NSMutableArray alloc] init];
[songs addObject:s];
}
-(void) detachSong: (Song *) s
{
[songs removeObjectIdenticalTo:s];
}
-(void)print
{
NSLog(@" ");
NSLog(@"--- Playlist: %s (%i songs)\n", [name UTF8String], [self numberOfSongs]);
for (Song * song in songs)
[song print];
NSLog(@" ");
}
-(void)search: (NSString *) searchFor
{
NSLog(@" ");
NSLog(@"++ Searched for \"%s\" in playlist \"%s\"", [searchFor UTF8String], [name UTF8String]);
for (Song *s in songs)
{
NSRange foundSong = [s.song rangeOfString:searchFor options: NSCaseInsensitiveSearch];
NSRange foundArtist = [s.artist rangeOfString:searchFor options: NSCaseInsensitiveSearch];
if (foundSong.location != NSNotFound || foundArtist.location != NSNotFound)
{
[s print];
}
}
NSLog(@" ");
}
-(void) dealloc
{
if (songs)
[songs release];
[name release];
[super dealloc];
}
-(id) initWithName: (NSString *) n
{
self = [super init];
[self setName:n];
return self;
}
@end
MusicCollection.h#import "Song.h"
#import "PlayList.h"
@interface MusicCollection : NSObject
{
NSString * name;
NSMutableArray * playlists;
}
@property (nonatomic, copy) NSString * name;
-(unsigned long) numberOfPlaylists;
-(unsigned long) numberOfSongs;
-(NSMutableArray *) playlists;
-(void) attachPlaylist: (PlayList *) playlist;
-(void) detachPlaylist: (PlayList *) playlist;
-(void)print;
-(void)search: (NSString *) searchFor;
-(void)dealloc;
-(id) initWithName: (NSString *) name;
@end
MusicCollection.m#import "MusicCollection.h"
@implementation MusicCollection
@synthesize name;
-(unsigned long) numberOfPlaylists
{
return [playlists count];
}
-(unsigned long) numberOfSongs
{
long songs = 0;
for (PlayList * pl in playlists)
songs += [pl numberOfSongs];
return songs;
}
-(NSMutableArray *) playlists
{
return [playlists copy];
}
-(void) attachPlaylist: (PlayList *) playlist
{
if (!playlists)
playlists = [[NSMutableArray alloc] init];
[playlists addObject:playlist];
}
-(void) detachPlaylist: (PlayList *) playlist
{
[playlists removeObjectIdenticalTo:playlist];
}
-(void)print
{
NSLog(@"=== Collection: %s (%i playlists, %i songs)", [name UTF8String], [self numberOfPlaylists], [self numberOfSongs]);
for (PlayList * playlist in playlists)
[playlist print];
}
-(void)search: (NSString *) searchFor
{
NSLog(@" ");
NSLog(@"++ Searched for \"%s\" in collection \"%s\"", [searchFor UTF8String], [name UTF8String]);
for (PlayList *p in playlists)
{
for (Song *s in [p getSongs])
{
NSRange foundSong = [s.song rangeOfString:searchFor options: NSCaseInsensitiveSearch];
NSRange foundArtist = [s.artist rangeOfString:searchFor options: NSCaseInsensitiveSearch];
if (foundSong.location != NSNotFound || foundArtist.location != NSNotFound)
{
[s print];
}
}
}
NSLog(@" ");
}
-(void) dealloc
{
if (playlists)
[playlists dealloc];
[super dealloc];
}
-(id) initWithName: (NSString *) n
{
self = [super init];
[self setName:n];
return self;
}
@end
15e9.m#import <Foundation/Foundation.h>
#import "Song.h"
#import "PlayList.h"
#import "MusicCollection.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Song * song1 = [[Song alloc] initWithArtist:@"Taylor Swift" andSong:@"You belong with me"];
Song * song2 = [[Song alloc] initWithArtist:@"Taylor Swift" andSong:@"Fifteen"];
Song * song3 = [[Song alloc] initWithArtist:@"Taylor Swift" andSong:@"Superstar"];
PlayList * pl1 = [[PlayList alloc] initWithName:@"Taylor Swift"];
[pl1 attachSong: song1];
[pl1 attachSong: song2];
[pl1 attachSong: song3];
Song * song4 = [[Song alloc] initWithArtist:@"James Morrison" andSong:@"You give me something"];
Song * song5 = [[Song alloc] initWithArtist:@"James Morrison" andSong:@"This boy"];
Song * song6 = [[Song alloc] initWithArtist:@"James Morrison" andSong:@"The only night"];
Song * song7 = [[Song alloc] initWithArtist:@"James Morrison" andSong:@"Get to you"];
PlayList * pl2 = [[PlayList alloc] initWithName:@"James Morrison"];
[pl2 attachSong: song4];
[pl2 attachSong: song5];
[pl2 attachSong: song6];
[pl2 attachSong: song7];
[pl2 detachSong: song6];
MusicCollection * mc = [[MusicCollection alloc] initWithName:@"Guido's Songs"];
[mc attachPlaylist:pl1];
[mc attachPlaylist:pl2];
[mc print];
[mc search:@"me"];
[mc dealloc];
[pl2 dealloc];
[pl1 dealloc];
[song1 dealloc];
[song2 dealloc];
[song3 dealloc];
[song4 dealloc];
[song5 dealloc];
[song6 dealloc];
[song7 dealloc];
[pool drain];
return 0;
}
I think that my solution is quite solid, but I can't wait to hear some good advise. Is this (one of) the way to do it, or is a bad solution? I've had my doubts about the "init" of "songs" (in "PlayList.m") and "playlists" (in "MusicCollection.m"), is there a better way? Oh, and is it leak-free?

Lot of questions, just don't wanna learn it the wrong way.
