如何使用NSPredicate过滤包含其他类的复合对象的NSMutableSet? [英] How to use NSPredicate to filter NSMutableSet which contains composite object from other Class?

查看:73
本文介绍了如何使用NSPredicate过滤包含其他类的复合对象的NSMutableSet?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新手问题,

我有3个类,其中3个是NSOBject的子类。

I have 3 Class, 3 of them are subclass from NSOBject.


  1. 集合类,具有2个属性, masterSong作为NSMutableSet (强,非原子)和 listOfPlaylists作为NSMutableArray (强,非原子)

  1. Collection Class, have 2 properties, masterSong as NSMutableSet (strong, nonatomic) and listOfPlaylists as NSMutableArray (strong, nonatomic)

播放列表类

具有2个属性, playListName为NSString (副本,非原子), songList为NSMutableArray (强,非原子)

Have 2 properties, playListName as NSString (copy, nonatomic) and songList as NSMutableArray (strong, nonatomic)

3。 歌曲类

具有4个属性:标题,艺术家,专辑,游戏时间(如NSString)(复制,非原子)。

Have 4 properties: title,artist,album, playtime as NSString (copy, nonatomic).

masterSong将包含Song对象,而listOfPlaylist将包含Playlist对象。

masterSong will contain Song object, and listOfPlaylist will contain Playlist Object.

而仅songList存储对Song Object的引用。

while songList only store reference to Song Object.

我想通过在MasterSong中查找标题,艺术家或专辑的Song来为Collection Class创建removeSong方法。

如果查找到find 1,它将返回NSSet,返回的NSSet将作为minusSet:方法中的参数,以从masterSong和所有Playlist.songList中删除歌曲。

但是,我不知道如何写下NSPredicate语法从包含歌曲对象的masterSong中过滤掉.title,.album或.artist。

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.

这是我到目前为止为
Collection.m

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
        ;
}

在执行lookUpTitle方法时,Xcode抛出异常,方法是说终止应用程序到期导致未捕获的异常 NSInvalidArgumentException,原因:无法在字符串中查找值(标题:Whole point of no return,艺术家:Cafe Bleu,专辑:CBSB,播放时间:3:56);值不是字符串

- (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;
    }
}

我知道主要的问题在于lookUpTitle方法

I know that the main problem is at lookUpTitle method

 NSPredicate *filter = [NSPredicate predicateWithFormat:filters, @"title", aName];

 NSSet *result = [masterSongs filteredSetUsingPredicate:filter];

过滤器以错误的方式过滤,而它应该过滤NSString对象(标题,艺术家或专辑),但masterSong包含Song Object,如何使用NSPredicate访问放置在masterSong内的Song Object中的标题,艺术家,专辑?

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.

编辑:根据响应者的要求添加部分代码(Class.m方法) #1。
这是与我的问题相关的.m文件中的某些方法

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;
    }
}

播放列表。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"];
}


推荐答案

您已经超载了 -removeSong:,它使您感到困惑。在播放列表中, -removeSong:接受一个 Song 实例,但在 Collection 中, -removeSong:接受 NSString 实例

You have overloaded the meaning of -removeSong: and it has caused you confusion. In Playlist, -removeSong: takes a Song instance, but in Collection, -removeSong: takes a NSString instance for the song title.

问题是您将 Song 的实例传递给期望 NSString

The problem is you pass an instance of a Song to the version which expects an NSString.

- (void)removeSong:(NSString *)zSong
{
    NSSet *targets = [self lookUpTitle:zSong];
    // …
}

应该是

- (void)removeSong:(Song *)aSong
{
    NSSet *targets = [self lookUpTitle:aSong.title];
    // …
}

- (void)removeSongWithTitle:(NSString *)aTitle
{
    NSSet *targets = [self lookUpTitle:aTitle];
    // …
}

我更改了第二个版本的名称清楚显示预期参数的方法。当您想使用第二个版本时,将传递消息 [myCollection removeSongWithTitle:aSong.title]

I changed the name of the second version of the method to clearly show what the expected parameter is. When you want to use the second version, you would pass the message [myCollection removeSongWithTitle:aSong.title]

这篇关于如何使用NSPredicate过滤包含其他类的复合对象的NSMutableSet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆