2011-04-08 31 views
0

我遇到了我创建的单例问题。它包含两个NSMutableDictionary,它们在应用程序中的三个视图(以及一些模式视图)中被读取和使用。设置单身字典导致EXC_BAD_ACCESS

我已经在地图上的字典里添加了一个MKMapView t图的一些场地。当我使用完全相同的方法/函数在其他视图中访问数据时,我收到与释放字典有关的EXC_BAD_ACCESS错误。这来自NSZombieEnabled:

CFDictionary retain: message sent to deallocated instance 

在dsym'ed跟踪,它与另一种引起悲伤更换一部字典。我使用调用该函数的代码来自一个MKAnnotationView点击:

UIControl *tempButton = sender; 
NSString *selectedEventsString = [self.eventsArray objectAtIndex:tempButton.tag]; 
NSLog(@"eventString: %@", selectedEventsString); 
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:selectedEventsString]; 

[tempButton release]; 
[selectedEventsString release]; 

“selectedEventsString”中走出来完全对应的事件。

在事件管理的相应的代码:

-(void)changeSelectedEventsDictionaryTo:(NSString *)eventName { 
     NSLog(@"singleton: %@", eventName); 
     self.eventString = eventName; 
     self.selectedEventsDictionary = [self.eventsDictionary objectForKey:eventName]; 
} 

两个selectedEventsDictionary和eventsDictionary被设置为@属性(非原子,保留)在.H文件,这是初始化函数:

+ (EventsManager*)eventsManager { 
    if (eventsManager == nil) { 
     eventsManager = [[super allocWithZone:NULL] init]; 
     eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.eventString = [[NSString alloc] init]; 
     eventsManager.mode = [[NSString alloc] init]; 
    } 

    return eventsManager; 
} 

这是在其他视图中使用的代码示例,其工作正常:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSUInteger row = [indexPath row]; 
    NSString *eventString = [self.eventsArray objectAtIndex:row]; 
    [[EventsManager eventsManager] changeSelectedEventsDictionaryTo:eventString]; 

    //Modal display code here 
} 

任何帮助将不胜感激!我想我已经提供了所有相关的代码,但是如果需要更多的代码,请告诉我。

干杯!

+0

好吧,刚刚解决它。但它真的很奇怪。在某些时候,我在MKAnnotationView中存储了一个额外的NSString来显示自定义数据。我停止使用它,但该变量仍然在.H文件中声明。当我删除它时,一切都落空了。 奇怪的,奇怪的错误。 – gamblor87 2011-04-08 23:39:19

回答

1

从哪里开始!我会指出一些我确实看错的东西。

第一个例子。不要释放tempButton和selectedEventString,因为你永远不会显式调用retain/copy或alloc和init。

UIControl *tempButton = sender; 
NSString *selectedEventsString = [self.eventsArray objectAtIndex:tempButton.tag]; 
NSLog(@"eventString: %@", selectedEventsString); 
[[EventsManager eventsManager] changeSelectedEventsDictionaryTo:selectedEventsString]; 

//DO NOT RELEASE THESE YOU NEVER RETAINED THEM! 
[tempButton release]; 
[selectedEventsString release]; 

你的静态事件管理不是线程安全的这可能不是你的问题,但一定要加以研究。

阅读留言给下面的代码示例

+ (EventsManager*)eventsManager { 
    if (eventsManager == nil) { //<-- Not thread safe 
     //DO NOT CALL SUPER USE self 
     //eventsManager = [[self alloc] init]; 
     eventsManager = [[super allocWithZone:NULL] init]; 

     //You need to autorelease these values or use an autoreleased static method 
     //eventsManager.eventsDictionary = [NSMutableDictionary dictionary]; 
     //eventsManager.selectedEventsDictionary = [NSMutableDictionary dictionary]; 
     eventsManager.eventsDictionary = [[NSMutableDictionary alloc] init]; 
     eventsManager.selectedEventsDictionary = [[NSMutableDictionary alloc] init]; 

     //Do not bother setting these at all or just set them to nil 
     eventsManager.eventString = [[NSString alloc] init]; 
     eventsManager.mode = [[NSString alloc] init]; 
    } 

    return eventsManager; 
} 

确保所有这些属性都设置保留或复制和可能解决您的问题。如果您在解决这些问题后仍然遇到问题,可以更新您的问题,我会更新我的答案。

+0

感谢您的出色答案。我是新手,这是我第一次真正使用单身人士,所以还是让我头脑发热。 改变eventsManager = [[super allocWithZone:NULL] init];到eventsManager = [[self alloc] init];当我第一次尝试使用EventsManager做任何事情时导致崩溃。 实施了其他更改(线程安全除外),结果没有变化。 NSZombie错误是:*** - [CFDictionary count]:发送到释放实例的消息0x2305f0 – gamblor87 2011-04-08 22:05:32

+0

还将添加XCode指出这是eventsDictionary,而不是selectedEventsDictionary。 – gamblor87 2011-04-08 22:11:47

+0

乔,感谢您的评论我已经重新让单身人士成为线程安全的,现在感觉更加自信。虽然它似乎不能直接解决问题,但它无疑使程序更好,并且我也是一个更好的程序员。所以谢谢! – gamblor87 2011-04-08 23:40:27