Objective c 如何使用NSPredicate筛选包含来自其他类的复合对象的NSMutableSet?

Objective c 如何使用NSPredicate筛选包含来自其他类的复合对象的NSMutableSet?,objective-c,cocoa-touch,nspredicate,nsmutableset,Objective C,Cocoa Touch,Nspredicate,Nsmutableset,新手问题 我有3个类,其中3个是NSOBject的子类 集合类,有两个属性,主歌曲作为NSMutableSet(强,非原子)和播放列表作为NSMUTABLEARY(强,非原子) 播放列表类 有两个属性,播放名为NSString(复制,非原子)和歌曲列表为NSMutableArray(强,非原子) 三,歌曲类 有4个属性:标题、艺术家、专辑、播放时间(复制、非原子) masterSong将包含歌曲对象,listOfPlaylist将包含播放列表对象 而歌曲列表只存储对歌曲对象的引用 我想通过在m

新手问题

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

  • 集合类,有两个属性,主歌曲作为NSMutableSet(强,非原子)和播放列表作为NSMUTABLEARY(强,非原子)

  • 播放列表类

  • 有两个属性,播放名为NSString(复制,非原子)和歌曲列表为NSMutableArray(强,非原子)

    三,歌曲类

    有4个属性:标题、艺术家、专辑、播放时间(复制、非原子)


    masterSong将包含歌曲对象,listOfPlaylist将包含播放列表对象

    而歌曲列表只存储对歌曲对象的引用

    我想通过在masterSong中查找歌曲的标题、艺术家或专辑,为Collection类创建removeSong方法。

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

    但是,我不知道如何写下NSPredicate语法,从包含Song对象的masterSong中筛选出.title或.album或.artist

    这是我到目前为止所得到的 收藏

    - (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在执行lookUpTitle方法时抛出异常,表示由于未捕获的异常而终止应用程序“NSInvalidArgumentException”,原因:“无法查找字符串中的值(标题:整点不归,艺术家: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;
        }
    }
    
    我知道主要的问题是查找方法

     NSPredicate *filter = [NSPredicate predicateWithFormat:filters, @"title", aName];
    
     NSSet *result = [masterSongs filteredSetUsingPredicate:filter];
    
    过滤器以错误的方式进行过滤,但它应该过滤NSString对象(标题、艺术家或唱片集),但masterSong包含歌曲对象,如何使用NSPredicate访问masterSong中放置的标题、艺术家、唱片集对象

    对于这种情况,还有其他有效的方法吗

    仅显示包含字符串的示例集/数组

    我找到了另一个线程,但block读起来很混乱,在我的例子中仍然不起作用


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

    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;
    }
    
    -(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;
        }
    }
    
    - (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:@""];
    }
    
     - (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"];
    }
    
    Playlist.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;
    }
    
    -(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;
        }
    }
    
    - (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:@""];
    }
    
     - (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"];
    }
    
    Song.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;
    }
    
    -(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;
        }
    }
    
    - (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:@""];
    }
    
     - (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"];
    }
    

    您不需要使用
    -predicateWithBlock
    ,在您的案例中使用以下谓词就足够了

    [NSPredicate predicateWithFormat:@"SELF.title CONTAINS %@", @"Layla"];
    
    编辑

    Jeffery Thomas是对的,问题就在这一行——事实上编译器给出了警告

     [myCollection removeSong:aSong];
    
    您正在向
    -removeSong:
    传递歌曲对象,而不是歌曲的标题。如果要传递到
    -removeSong:
    a
    Song
    对象,则将方法签名从
    -(void)removeSong:(NSString*)songtile
    更改为
    -(void)removeSong:(Song*)Song
    ,并相应地更改方法实现以传递给谓词歌曲的标题,该标题是
    NSString

    - (void) removeSong: (Song *)zSong {
    
        //remove from reference playlist
        NSSet *targets = [self lookUpTitle:zSong.title];
    
        if ([targets count]>0) {
            [self.masterSongs minusSet:targets];
    
            for (Playlist *playlist in self.listOfPlaylists) {
                // -all objects converts the set into array.
    
                [playlist.songList removeObjectsInArray:[targets allObjects]];
            }
        }
    }
    

    从现在起,请不要忽略编译器警告,以避免在调试此类细微错误的过程中花费数天时间。

    您不需要使用
    -predicateWithBlock
    ,在您的情况下使用以下谓词就足够了

    [NSPredicate predicateWithFormat:@"SELF.title CONTAINS %@", @"Layla"];
    
    编辑

    Jeffery Thomas是对的,问题就在这一行——事实上编译器给出了警告

     [myCollection removeSong:aSong];
    
    您正在向
    -removeSong:
    传递歌曲对象,而不是歌曲的标题。如果要传递到
    -removeSong:
    a
    Song
    对象,则将方法签名从
    -(void)removeSong:(NSString*)songtile
    更改为
    -(void)removeSong:(Song*)Song
    ,并相应地更改方法实现以传递给谓词歌曲的标题,该标题是
    NSString

    - (void) removeSong: (Song *)zSong {
    
        //remove from reference playlist
        NSSet *targets = [self lookUpTitle:zSong.title];
    
        if ([targets count]>0) {
            [self.masterSongs minusSet:targets];
    
            for (Playlist *playlist in self.listOfPlaylists) {
                // -all objects converts the set into array.
    
                [playlist.songList removeObjectsInArray:[targets allObjects]];
            }
        }
    }
    

    从现在起,请不要忽略编译器警告,以避免在调试此类细微错误的过程中花费数天时间。

    您已经过多地理解了
    -removeSong:
    的含义,这已经给您带来了困惑。在
    Playlist
    -removeSong:
    采用
    歌曲
    实例,但在
    收藏
    中,
    -removeSong:
    采用歌曲标题的
    NSString
    实例

    问题是您将
    歌曲的一个实例传递给需要
    NSString
    的版本

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

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


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

    您已经重载了
    -removeSong:
    的含义,这会造成您的混淆。在
    Playlist
    -removeSong:
    采用
    歌曲
    实例,但在
    收藏
    中,
    -removeSong:
    采用歌曲标题的
    NSString
    实例

    问题是您将
    歌曲的一个实例传递给需要
    NSString
    的版本

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

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


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

    我也用它进行了测试,但它不起作用。Xcode仍然引发异常:由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无法对非字符串的内容执行子字符串操作。”。我知道masterSong本身包含Song对象,如果使用您建议的代码,它不会尝试用字符串过滤Song对象吗?您能更好地解释到底什么包含masterSong吗?你确定这是一个套餐吗