Objective c 如何使用NSPredicate筛选包含来自其他类的复合对象的NSMutableSet?
新手问题 我有3个类,其中3个是NSOBject的子类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
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:
aSong
对象,则将方法签名从-(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:
aSong
对象,则将方法签名从-(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吗?你确定这是一个套餐吗