在单例中设置字典导致EXC_BAD_ACCESS

时间:2011-04-08 15:05:00

标签: iphone ios singleton mkmapview

我遇到了我创建的单身人士的问题。它包含两个NSMutableDictionary,它们在整个应用程序中的三个视图(和一些模态视图)中被读取和使用。

我在地图上添加了一个MKMapView,用于绘制字典中的一些场所。当我使用在每个其他视图中使用的完全相同的方法/函数来访问数据时,我收到与解除分配的字典有关的EXC_BAD_ACCESS错误。这来自NSZombieEnabled:

CFDictionary retain: message sent to deallocated instance

在dsym的追踪中,它是用另一个字典取代导致悲伤的字典。我用来调用函数的代码来自MKAnnotationView点击:

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

[tempButton release];
[selectedEventsString release];

“selectedEventsString”将出现一个完全相应的事件。

EventsManager中的相应代码:

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

在.H文件中,selectedEventsDictionary和eventsDictionary都设置为@property(nonatomic,retain),这是init函数:

+ (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
}

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

干杯!

1 个答案:

答案 0 :(得分: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*)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;
}

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

相关问题