【问题标题】:How to modify NSMutableSet using Fast Enumerations with NSPredicate as filter如何使用 NSPredicate 作为过滤器的快速枚举修改 NSMutableSet
【发布时间】:2014-03-22 10:57:35
【问题描述】:

新手问题,

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

一个。集合类

这个类将有 2 个属性

  1. masterSongs(包含所有歌曲)声明为 NSMUtableSet(副本,非原子)
  2. listofPlaylists(包含所有播放列表)声明为 NSMutableArray(副本,非原子)

b.播放列表类

这个类将有 2 个属性

  1. playListName 声明为 NSString
  2. songLists 声明为 NSMutableArray(强,非原子),仅存储对歌曲的引用而不是歌曲的副本。

c.歌曲类

这个类有 4 个属性声明为 NSString :

  1. 标题
  2. 艺术家
  3. 上场时间
  4. 专辑

问题:

  1. 我想为 Collection 类创建 removeSong 方法,所以当我从 Collection (masterSongs) 中删除特定歌曲时,它也会删除 Collection.listofPlaylists 中存储的所有 playList 中的歌曲。但我被语法困住了*。

*我正在使用查找方法创建一个 NSSet,然后使用该集合从 NSMutableSet masterSongs 中删除歌曲对象,使用 - minusSet: 方法

另外,我 found that 在枚举时更改修改 NSMutableSet 很危险。

到目前为止我在这里尝试过:

- (NSSet *) lookUpTitle: (NSString *)aName {

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

NSSet *result = [self.masterSongs filteredSetUsingPredicate:filter];

if ([result count] == 0) {
    NSLog(@"not found");

    return nil;
}


else{
    return result;
}

}

- (void) removeSong: (NSString *)zSong{


    for (Song *aSong in masterSongs) {



        if ([self lookUpTitle:zSong] != nil) {

            NSMutableSet *container = [NSMutableSet setWithSet:self.masterSongs];
        }

    }

}



 - (void) addSong :(Song *)aSong{
    if (![masterSongs containsObject:aSong]) {

        [masterSongs addObject:aSong];

    } }

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

}

【问题讨论】:

  • 只是为了强调一点,尽管您确实提到了它,但您不能在枚举集合(集合、数组、字典)时对其进行变异。如果您这样做,它可以(应该并且可能会)抛出异常。

标签: objective-c nspredicate nsset


【解决方案1】:

-lookUpTitle: 为您完成大部分工作。它返回一组需要删除的歌曲。您使用-minusSet: 将它们从NSMutableSet 中删除。要从播放列表中删除歌曲,您需要循环播放播放列表并删除集合中的歌曲。您可以使用-removeObjectsInArray: 将它们从NSMutableArray 中删除。

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

    if ([targets count] > 0) {
        [self.masterSongs minusSet:targets];

        for (Playlist *playlist in self.listOfPlaylists) {
            // -allObjects converts the set into an array.
            [playlist.songLists removeObjectsInArray:[targets allObjects]];
        }
    }
}

您提出了一个关于属性的新问题。

@property (copy) NSMutableSet *masterSongs;

是个坏主意。会自动生成一个-setMasterSongs: 方法,如下所示:

- (void)setMasterSongs:(NSMutableSet *)masterSongs
{
    if (_masterSongs != masterSongs) {
        _masterSongs = [masterSongs copy];
    }
}

问题是-[NSMutableSet copy]返回一个NSSet;同样,-[NSMutableArray copy] 返回NSArray。这就是你遇到问题的原因。 NSSetNSArray 是不可变的,因此它们不包含任何会改变其内容的方法。

【讨论】:

  • 抱歉回复晚了,昨天下线了。我对财产申报有疑问。我声明:NSMutableSet 和 NSMutableArray 为 Copy,Collection Class 上的 Nonatomic 并且我还声明 NSMutableArray 在 Playlist 类上是强的、非原子的,这种情况,当我运行 Collection 实例方法 addSong:(Song *)aSong 或方法 addPlaylist:(Playlist *) aList 两种方法都抛出无法识别的选择器异常。但是当我将集合类属性 NSMutableArray 和 NSMutableSet 都更改为强的、非原子的时,它运行正常。那么,副本不能包含引用或什么?
  • 关于我最后一个问题的一些信息在这里stackoverflow.com/questions/3220120/… 但我仍然不明白,为什么在 addSong 方法中复制抛出异常,虽然 Collection Class masterSongs 声明为复制、非原子和 Song 属性声明为副本
  • @user3213703 这些是新问题。你真的应该把它们作为一个新问题发布,而不是把它们附加到一个不相关的问题上。
  • @user3213703 我更新了我的答案,对你的新问题作了简短回答。
  • 感谢您的回答和建议,我会记住的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多