Установка словаря в синглтоне вызывает EXC_BAD_ACCESS - PullRequest
0 голосов
/ 08 апреля 2011

У меня проблемы с синглтоном, который я создал. Он содержит два 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 Ответ

1 голос
/ 08 апреля 2011

С чего начать! Я укажу некоторые вещи, которые я вижу неправильно.

Первый пример. Не выпускайте 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;
}

Убедитесь, что все эти свойства настроены для сохранения или копирования, и это может решить вашу проблему. Если после этих исправлений у вас все еще остается проблема, вы можете обновить свой вопрос, а я обновлю свой ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...