Установка NSMatrix выбора программно вызывает блокировку мьютекса при попытке позже получить выбранную ячейку

обзор

Я вижу странную проблему в приложении Mac OS X Cocoa, которое я разрабатываю с Xcode 4.3.2 и тестирую на Mac OS X 10.7.5 (для Mac OS X 10.6): у меня есть базовая радиогруппа NSMatrix основной NIB, который имеет один выход и одно действие в моем главном контроллере, но также используется в двух других методах (также в главном контроллере). Действие сохраняет выбранный тег в NSUserDefaults и включает / отключает NSTextField, на основе которого выбран, один метод является загрузчиком настроек и поэтому выбирает ячейку по тегу при загрузке, а другой метод ищет выбранный тег для другой логики (код Образцы ниже).

Базовые вещи, но в одном случае (когда программно выбирается только ячейка в NSMatrix, а не с помощью переключателя в графическом интерфейсе), приложение блокирует блокировку мьютекса.

Код и функциональность

Я переименовал переменные и методы ниже, но не изменил ни одну другую структуру кода. passwordRadioGroup это NSMatrix* IBOutlet.

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
    // get logging up and running
    [self initLogging];

    // load various prefs
    // ...
    [self loadPasswordSettings];
}

- (void)loadPasswordSettings {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // load password settings from our prefs
    NSNumber *passwordTypeTag = [defaults objectForKey:kPasswordTypeDefaultKey];
    if ( passwordTypeTag != nil ) {
        [passwordRadioGroup selectCellWithTag:[passwordTypeTag intValue]];
    } else {
        [passwordRadioGroup selectCellWithTag:kPasswordTypeRadioRandomTag];
    }
    [self selectPasswordType:passwordRadioGroup];

    // ...
}

- (IBAction)selectPasswordType:(NSMatrix *)sender {
    NSInteger tag = [[sender selectedCell] tag];
    switch ( tag ) {
        case kPasswordTypeRadioRandomTag:
            // disable the password text field
            [passwordField setEnabled:NO];
            break;
        case kPasswordTypeRadioManualTag:
            // enable the password text field
            [passwordField setEnabled:YES];
            break;
    }
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:tag] forKey:kPasswordTypeDefaultKey];
}

- (NSString *)generateUserPassword {
    NSString *password;

    // which type of password should we be generating (random or from a specifed one)?
    NSInteger tag = [[passwordRadioGroup selectedCell] tag];
    switch ( tag ) {
        // manual password
        case kPasswordTypeRadioManualTag:
            password = [passwordField stringValue];
            break;
        // random password
        case kPasswordTypeRadioRandomTag:
            // password = randomly generated password;
            break;
    }

    return password;
}

Когда приложение запускается, мой главный контроллер отправляется applicationDidFinishLaunching сообщение, которое затем отправляет loadPasswordSettings сообщение для себя. loadPasswordSettings затем отправляет [[passwordRadioGroup selectedCell] tag] и отправляет [passwordRadioGroup selectCellWithTag:], Это работает правильно, и правильный переключатель выбран в графическом интерфейсе. Наконец звонит [self selectPasswordType:passwordRadioGroup (который также успешно вызывает [[passwordRadioGroup selectedCell] tag]) и соответственно включает / отключает текстовое поле и записывает тег обратно в NSUserDefaults (обычно, но не всегда избыточно).

Вы можете выбрать любую из переключателей, которая отправляет selectPasswordType: сообщение на мой главный контроллер (передавая его экземпляр passwordRadioGroup; Я проверил адрес памяти в отладчике и могу проверить его ивары). Это успешно звонки [[passwordRadioGroup selectedCell] tag] и сохраняет тег в NSUserDefaults.

Вы можете сделать это два раза столько раз, сколько хотите, без проблем. Выход и повторный запуск корректно восстанавливают переключатели в состояние, в котором вы оставили их последними, поэтому он определенно правильно получает выбранный тег, сохраняет его по умолчанию в NSUser, извлекает его из NSUserDefaults и устанавливает выбранную ячейку по тегу в NSMatrix.

Вот где это становится ввернутым:

Есть еще одна кнопка, которая при нажатии выполняет кучу другой работы и, в конечном итоге, отправляет generateUserPassword сообщение самому себе для создания пароля (опять же, это все в главном контроллере и работает в главном потоке). Каково первое, что он делает? Вызовы [[passwordRadioGroup selectedCell] tag], Хорошо, вы можете безопасно делать это столько, сколько хотите, как показано выше, верно?

Если вы выберете одну из переключателей, то измените выбранную ячейку через графический интерфейс и отправьте selectPasswordType: сообщение для моего главного контроллера снова, да. Вы не столкнетесь с проблемами (хотя, я признаю, это кажется немного медленным и PWOD на секунду).

Если вы не нажмете на NSMatrix после запуска (чтобы не вызывать выбор / действие снова из GUI), это [[passwordRadioGroup selectedCell] tag] вызывать generateUserPassword будет сразу PWOD. Если я нажимаю кнопку паузы в отладчике XCode, чтобы увидеть, где он находится, он всегда находится в psych_mutexwait (вызывается из class_lookupMethodAndLoadCache) в основной теме. Если selectPasswordType: не были вызваны программно и не могут работать [[passwordRadioGroup selectedCell] tag] без проблем я бы хоть немного здравомыслия оставил.

Помогите!

Повторюсь, я проследил это в отладчике и могу убедиться, что адрес памяти и ivars подтверждают, что passwordRadioGroup не меняется из-под меня и не освобождается (я пробовал с & без "Zombie Objects"). Единственные ссылки на passwordRadioGroup в моем главном контроллере те, которые видели выше. Поиск в Google для всех видов NSMatrix/ радио /selectCellWithTag/selectedCell/selectedTag/class_lookupMethodAndLoadCache/ мьютекс термины / комбинации не был плодотворным.

Любые решения, предложения по устранению неполадок или мысли будут с благодарностью. Пощечины за глупость тоже приветствуются, если заслужили.

0 ответов

Другие вопросы по тегам