Iphone Can';t从NSMutableSet添加或删除对象
检查它:Iphone Can';t从NSMutableSet添加或删除对象,iphone,objective-c,Iphone,Objective C,检查它: - (IBAction)toggleFavorite { DataManager *data = [DataManager sharedDataManager]; NSMutableSet *favorites = data.favorites; if (thisEvent.isFavorite == YES) { NSLog(@"Toggling off"); thisEvent.isFavorite = NO;
- (IBAction)toggleFavorite {
DataManager *data = [DataManager sharedDataManager];
NSMutableSet *favorites = data.favorites;
if (thisEvent.isFavorite == YES) {
NSLog(@"Toggling off");
thisEvent.isFavorite = NO;
[favorites removeObject:thisEvent.guid];
[favoriteIcon setImage:[UIImage imageNamed:@"notFavorite.png"] forState:UIControlStateNormal];
}
else {
NSLog(@"Toggling on, adding %@", thisEvent.guid);
thisEvent.isFavorite = YES;
[favorites addObject:thisEvent.guid];
[favoriteIcon setImage:[UIImage imageNamed:@"isFavorite.png"] forState:UIControlStateNormal];
}
NSLog(@"favorites array now contains %d members", [favorites count]);
}
这是从自定义UIButton触发的。UI部分工作得很好——切换用于按钮的图像,我可以从其他内容中看到thisEvent.isFavorite BOOL正在愉快地切换。我还可以在调试器中看到我正在获得DataManager单例
但这是我的日志:
2010-05-13 08:24:32.946 MyApp[924:207] Toggling on, adding 05db685f65e2
2010-05-13 08:24:32.947 MyApp[924:207] favorites array now contains 0 members
2010-05-13 08:24:33.666 MyApp[924:207] Toggling off
2010-05-13 08:24:33.666 MyApp[924:207] favorites array now contains 0 members
2010-05-13 08:24:34.060 MyApp[924:207] Toggling on, adding 05db685f65e2
2010-05-13 08:24:34.061 MyApp[924:207] favorites array now contains 0 members
2010-05-13 08:24:34.296 MyApp[924:207] Toggling off
2010-05-13 08:24:34.297 MyApp[924:207] favorites array now contains 0 members
最糟糕的是,这曾经奏效,我不知道我做了什么来打破它
--编辑:根据请求,我的共享数据单例代码:
h
------编辑编辑编辑------
在@TechZen的建议下,我将访问器方法移到了数据管理器单例中。下面是它现在的样子:
#import "DataManager.h"
static DataManager *singletonDataManager = nil;
@implementation DataManager
@synthesize eventList;
@synthesize favorites;
+(DataManager*)sharedDataManager {
@synchronized(self) {
if (!singletonDataManager) {
singletonDataManager = [[DataManager alloc] init];
}
}
return singletonDataManager;
}
- (DataManager*)init {
if (self = [super init]) {
eventList = [[NSMutableArray alloc] init];
favorites = [[NSMutableSet alloc] init];
}
return self;
}
#pragma mark -
#pragma mark Data management functions
- (void)addToFavorites:(NSString *)guid
{
[self.favorites addObject:guid];
NSLog(@"Item added--we now have %d faves.", [favorites count]);
}
- (void)removeFromFavorites:(NSString *)guid
{
[favorites removeObject:guid];
NSLog(!"Item removed--we now have %d faves.", [self.favorites count]);
}
@end
我让我的viewcontroller调用[[DataManager sharedManager]addToFavorites:Event.guid]
,而不是将项目直接添加到收藏夹集本身,但我保留了那里的日志记录
这是我的日志:
2010-05-13 13:25:52.396 EverWondr[8895:207] Toggling on, adding 05db685f65e2
2010-05-13 13:25:52.397 EverWondr[8895:207] Item added--we now have 0 faves.
2010-05-13 13:25:52.398 EverWondr[8895:207] favorites array now contains 0 members
2010-05-13 13:25:53.578 EverWondr[8895:207] Toggling off
2010-05-13 13:25:53.579 EverWondr[8895:207] favorites array now contains 0 members
所以。。。。DataManager对象甚至不能向其自身属性添加任何内容!而且它不会像不可变类型那样抛出异常,它只是默默地失败了
只是为了好玩,我把它改成了我更熟悉的NSMutableArray。相同的行为。正如上面phellicks所建议的,您可能没有从
data.favorites
返回可变集。不过,如果是这种情况,您应该会收到编译器警告
此05db685f65e2
不是真正的guid。它看起来更像一个对象的地址。您应该检查“thisEvent.guid”上的类型,以确保您获得了一个对象和正确的对象类型
与您的主要问题无关,我想补充一点(1)这:
。。。是毫无意义的,只是增加了另一个可能的错误源。没有理由不直接在代码中使用数据。收藏夹。(见下文第(3)段)
(2) 当访问外部对象(甚至是单例对象)时,最好将对外部对象的引用作为类的属性,特别是在关键对象(如数据模型)的情况下。这使您可以控制和跟踪对外部对象的访问
(3) 不要将单例视为裸全局变量。这将导致悲伤。相反,将对数据模型内部数据的访问包装到特定方法中。例如,不访问数据。收藏夹
直接创建一个方法,如:
- (void) addToFavoritesGuid:(id) aGuid;
或
这将使您的数据模型能够控制其内部,并使其能够拒绝添加不应属于其中的对象
编辑
从评论中:
好吧,你就是我
返回。。。我只是用debug来调试
通过我的singleton初始化器。
检查我的数据管理器的IVAR
对象,我看到我的收藏夹
使用收藏夹在init中初始化
=[[NSMutableSet alloc]init];实际上被创建为NSCFSet,
我不知道那是什么,也不知道那是什么
为了使它成为现实
NSSet与所有集合和字符串一样,实际上是一个类集群,即共享同一接口的子类集合。当你创建一个集合时,你得到的实际类可能会有所不同,这取决于它是如何创建的。在本例中,您将返回NS Core Foundation Set,它是NSSet的标准核心类
因此,您的问题是,收藏夹
被初始化为可变集,但被分配给不可变集。这就是为什么你不能添加任何内容
此初始化:
favorites = [[NSMutableSet alloc] init];
。。。正在由以下机构处置:
NSMutableSet *favorites = data.favorites;
如果您有一个实例变量,并且创建了一个同名的局部变量,则局部符号将在创建它的范围内起主导作用。这似乎是可行的,因为作为NSSet的子类,NSMutableSet响应NSSet的所有方法和属性
但是,在构建时,您一定会从链接器中收到大量警告。你不应该忽视这些错误。您应该将它们视为致命错误,因为它们在运行时就是致命错误
要解决您的问题,请执行以下操作:
(1) 将data.favorites声明为可变数组,直接访问即可。将另一个局部变量分配给同一地址不会给您带来任何好处
(2) 将收藏夹声明为当前对象的可变数组属性。从数据初始化它。收藏夹类似于:
self.favorites=[NSMutableSet setWithCapacity:[data.favorites count]];
[self.favorites集合:data.favorites];
// ... 添加或删除项目
data.favorites=self.favorites
(3) 将data.favorites中用于添加或删除对象的所有逻辑移动到数据模型对象中的自定义方法(请参见上文)
三个是最好的选择
Edit02
看起来类集群隐藏了集群中所有类的真实类。我运行了以下测试代码:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSSet *s=[NSSet setWithObject:@"setWithObject"];
NSMutableSet *m=[NSMutableSet setWithCapacity:1];
[m addObject:@"Added String"];
NSMutableSet *n = [[NSMutableSet alloc] initWithCapacity:1];
[self showSuperClasses:s];
[self showSuperClasses:m];
[self showSuperClasses:n];
[self showSuperClasses:@"Steve"];
}
- (void) showSuperClasses:(id) anObject{
Class cl = [anObject class];
NSString *classDescription = [cl description];
while ([cl superclass])
{
cl = [cl superclass];
classDescription = [classDescription stringByAppendingFormat:@":%@", [cl description]];
}
NSLog(@"%@ classes=%@",[anObject class], classDescription);
}
。。。得到了这个输出:
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFString classes=NSCFString:NSMutableString:NSString:NSObject
显然,来自调试器的报告和class函数在确定属于集群的任何实例的真实类时是无用的。过去不是这样的。这是最近的变化。我假设它是核心基金“免费桥接”的一部分。
您可以将项目添加到收藏夹,因为这两个类中的收藏夹的所有定义都是NSMutableSet
无论如何,您的问题是在同一个类中有两个不同的收藏夹定义。链接器会向您发出警告,警告您:
本地声明“收藏夹”隐藏实例变量
我认为这个问题可以解释为运行时混淆了两个收藏夹。将对象添加到一个收藏夹中,但记录另一个收藏夹
对收藏夹的本地重新定义毫无用处。将其删除,看看问题是否仍然存在 正如上面phellicks所建议的,您可能无法从data.favorites
返回可变集。不过,如果是这种情况,您应该会收到编译器警告
这个<
favorites = [[NSMutableSet alloc] init];
NSMutableSet *favorites = data.favorites;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSSet *s=[NSSet setWithObject:@"setWithObject"];
NSMutableSet *m=[NSMutableSet setWithCapacity:1];
[m addObject:@"Added String"];
NSMutableSet *n = [[NSMutableSet alloc] initWithCapacity:1];
[self showSuperClasses:s];
[self showSuperClasses:m];
[self showSuperClasses:n];
[self showSuperClasses:@"Steve"];
}
- (void) showSuperClasses:(id) anObject{
Class cl = [anObject class];
NSString *classDescription = [cl description];
while ([cl superclass])
{
cl = [cl superclass];
classDescription = [classDescription stringByAppendingFormat:@":%@", [cl description]];
}
NSLog(@"%@ classes=%@",[anObject class], classDescription);
}
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFSet classes=NSCFSet:NSMutableSet:NSSet:NSObject
NSCFString classes=NSCFString:NSMutableString:NSString:NSObject