Newbie Questions,
I have 3 Class, 3 of them are subclass from NSOBject.
Collection Class, have 2 properties, masterSong as NSMutableSet (strong, nonatomic) and listOfPlaylists as NSMutableArray (strong, nonatomic)
Playlist Class
Have 2 properties, playListName as NSString (copy, nonatomic) and songList as NSMutableArray (strong, nonatomic)
3 . Song Class
Have 4 properties: title,artist,album, playtime as NSString (copy, nonatomic).
masterSong will contain Song object, and listOfPlaylist will contain Playlist Object.
while songList only store reference to Song Object.
I want to create removeSong method for Collection Class by looking up Song for title,artist,or album inside masterSong.
if looking up find 1, it will return NSSet, returned NSSet will take place as parameter in minusSet: method to remove the song from masterSong and all Playlist.songList.
but, I can't figure out how to write down NSPredicate syntax to filter out .title or .album or .artist from masterSong which contain Song Object.
here is what I got so far, for Collection.m
- (void) removeSong: (NSString *)zSong{
//remove from reference playlist
NSSet *targets = [self lookUpTitle:zSong];
if ([targets count]>0) {
[self.masterSongs minusSet:targets];
for (Playlist *playlist in listOfPlaylists) {
// -all objects converts the set into array.
[playlist.songList removeObjectsInArray:[targets allObjects]];
}
}
else
;
}
Xcode throw exception when executing lookUpTitle method by saying that Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't look for value (title:Whole point of no return ,artist: Cafe Bleu ,album: CBSB ,playtime: 3:56) in string (What Do You Know); value is not a string
- (NSSet *) lookUpTitle: (NSString *)aName {
NSString *filters = @"%K CONTAINS [cd] %@";
NSPredicate *filter = [NSPredicate predicateWithFormat:filters, @"title", aName];
NSSet *result = [masterSongs filteredSetUsingPredicate:filter];
if ([result count] == 0) {
NSLog(@"not found");
return nil;
}
else{
return result;
}
}
I know that the main problem is at lookUpTitle method
NSPredicate *filter = [NSPredicate predicateWithFormat:filters, @"title", aName];
NSSet *result = [masterSongs filteredSetUsingPredicate:filter];
the filter is filtering in a wrong way, while it should filtering NSString object (title, artist, or album) but masterSong is containing Song Object, how do I access title,artist,album in Song Object placed inside masterSong with NSPredicate?
any other effective way for this condition?
Predicate Programming Guide only show example set/array containing string
I found other thread which has similar topic, but block is quite confusing to read, and still won't work in my case.
Edit : additions to the partial code (Class.m method) as requested by responder #1 . here are some method in .m files related to my questions
Main.m
#import <Foundation/Foundation.h>
#import "MusicCollection.h"
#import "Playlist.h"
#import "Song.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// insert code here...
// NSLog(@"Hello, World!");
//create Songs
Song *aSong = [[Song alloc]initWithTitle:@"Whole point of no return" withArtist:@"Cafe Bleu" withAlbum:@"CBSB" withPlaytime:@"3:56"];
Song *bSong = [[Song alloc]initWithTitle:@"Council Meetin'" withArtist:@"Cafe Bleu" withAlbum:@"CBSB" withPlaytime:@"4:00"];
Song *cSong = [[Song alloc]initWithTitle:@"Hayate" withArtist:@"Spitz" withAlbum:@"Indigo Chiheisen" withPlaytime:@"4:21"];
Song *dSong = [[Song alloc]initWithTitle:@"I have a Dreams" withArtist:@"WestLife" withAlbum:@"Season" withPlaytime:@"4:11"];
Song *eSong = [[Song alloc]initWithTitle:@"What Do You Know" withArtist:@"David Choi" withAlbum:@"Tomorrow" withPlaytime:@"3:46"];
//create playList
Playlist *playlistA = [[Playlist alloc]initWithName:@"Playlist A"];
Playlist *playListB = [[Playlist alloc]initWithName:@"Playlist B"];
//store Song A & B to Playlist A and Song A,B,C to playlist B
[playlistA addSong:aSong];
[playlistA addSong:bSong];
[playListB addSong:aSong];
[playListB addSong:bSong];
[playListB addSong:cSong];
// [playListB removeSong:eSong];
//Creating Master Collection
MusicCollection *myCollection = [[MusicCollection alloc]initWithName:@"Library"];
[myCollection addPlaylist:playlistA];
[myCollection addPlaylist:playListB];
[myCollection addSong:eSong];
[myCollection addSong:dSong];
[myCollection removePlaylist:playListB];
[myCollection removeSong:aSong];
NSSet *container2 = [myCollection lookUpTitle:@"What"];
NSLog(@"%@",container2);
// NSLog(@"%@",myCollection);
}
return 0;
}
Collection.m
-(instancetype) initWithName: (NSString *)aName{
self = [super init];
if (self) {
self.name = [NSMutableString stringWithString:aName];
self.listOfPlaylists = [NSMutableArray array];
self.masterSongs = [NSMutableSet set];
}
return self;
}
-(instancetype) init{
return [self initWithName:@""];
}
-(void) addPlaylist: (Playlist *)aPlayList{
if ([listOfPlaylists containsObject:aPlayList]==YES) {
}
else
[listOfPlaylists addObject:aPlayList];
}
-(void) removePlaylist: (Playlist *)aPlayList{
if ([listOfPlaylists containsObject:aPlayList]) {
[listOfPlaylists removeObjectIdenticalTo:aPlayList];
}
else{
;
}
}
- (void) displaySong{
NSLog(@"displaying all song in Collection");
NSLog(@" %@",self.masterSongs);
}
- (void) addSong :(Song *)aSong{
if (![masterSongs containsObject:aSong]) {
[masterSongs addObject:aSong];
}
}
- (void) removeSong: (NSString *)zSong{
//remove from reference playlist
NSSet *targets = [self lookUpTitle:zSong];
if ([targets count]>0) {
[self.masterSongs minusSet:targets];
for (Playlist *playlist in listOfPlaylists) {
// -all objects converts the set into array.
[playlist.songList removeObjectsInArray:[targets allObjects]];
}
}
else
;
}
- (NSSet *) lookUpTitle: (NSString *)aName {
NSString *filters = @"%K CONTAINS [cd] %@";
NSPredicate *filter = [NSPredicate predicateWithFormat:filters, @"title", aName];
NSSet *result = [masterSongs filteredSetUsingPredicate:filter];
if ([result count] == 0) {
NSLog(@"not found");
return nil;
}
else{
return result;
}
}
Playlist.m
- (void) addSong :(Song *)aSong{
if (![songList containsObject:aSong]) {
[songList addObject:aSong];
}
}
- (void) removeSong: (Song *)aSong{
if ([songList containsObject:aSong]){
[self.songList removeObjectIdenticalTo:aSong];
}
}
- (instancetype) initWithName: (NSString *)aPLName{
self = [super init];
if (self) {
self.songList = [NSMutableArray array];
self.playlistName = aPLName;
}
return self;
}
- (instancetype)init{
return [self initWithName:@""];
}
Song.m
- (instancetype) initWithTitle: (NSString *)aTitle withArtist: (NSString *)anArtist withAlbum: (NSString *)aAlbum withPlaytime: (NSString *)playingTime{
self = [super init];
if (self) {
self.artist = [NSMutableString stringWithString:anArtist];
self.album = [NSMutableString stringWithString:aAlbum];
self.title = [NSMutableString stringWithString:aTitle];
self.playtime = [NSMutableString stringWithString:playingTime];
}
return self;
}
-(instancetype) init{
return [self initWithTitle:@"null" withArtist:@"null" withAlbum:@"null" withPlaytime:@"null"];
}