Обновление динамически создаваемого NSMenu с помощью NSMenuItems - PullRequest
0 голосов
/ 16 сентября 2011

У меня есть NSMenu с 3 статическими NSMenuItems, которые я хочу сохранить, и куча после этого генерируется динамически и должна удаляться и перезагружаться каждый раз, когда пользователь щелкает значок меню.

Я пытаюсь создать список процессов, которые выскочат, но каждый раз, когда я открываю всплывающее окно, NSMenuItems не очищается. Они просто добавляются каким-то странным способом. Регистрация цикла for показывает, что цикл не завершается. Есть идеи почему?

-(void)menuNeedsUpdate:(NSMenu *)menu{

    //Keep Top 3 Menu Items
    if(dropDown.numberOfItems > 3){
        NSLog(@"-----------Removing Items");
        NSLog(@"%d",itemCount);
        for(int i = 2; i <= dropDown.numberOfItems; i++){
            NSLog(@"%d",i);
            [dropDown removeItemAtIndex:i];

        }
    }

    NSArray *appArray = [[NSWorkspace sharedWorkspace] runningApplications];


    for (NSRunningApplication *r in appArray){
        //NSLog(r.localizedName);
        //NSLog(@"------------");
        NSMenuItem *i = [[NSMenuItem alloc] initWithTitle:r.localizedName 
                                               action:@selector(fooClicked:) keyEquivalent:@""];
        [i setTarget:self];
        [dropDown addItem:i];

        [i release];
    }


}

1 Ответ

1 голос
/ 16 сентября 2011

ваша проблема с кодом удаления. Учтите это:

for(int i = 3; i <= dropDown.numberOfItems; i++){
    NSLog(@"%d",i);
    [dropDown removeItemAtIndex:i];
}

Это должно быть i-- в конце. Также - если массив имеет 3 элемента, индекс последнего элемента равен 2, поэтому объявление цикла должно быть следующим:

for(int i = 2; i >= 0; i--){
    NSLog(@"%d",i);
    [dropDown removeItemAtIndex:i];
}

Обновление по комментарию

Удаление элементов из вашего меню должно выполняться назад или вперед, но удаление того же индекса элемента сразу после 2-го элемента (т.е. удаление всегда 3-го элемента):

for(int i = 2; i <= dropDown.numberOfItems; i++){
    NSLog(@"%d",i);
    [dropDown removeItemAtIndex:2];
}

или

for(int i = dropDown.numberOfItems; i >= 2; i--){
    NSLog(@"%d",i);
    [dropDown removeItemAtIndex:i];
}

Это необходимо, потому что каждый раз, когда вы удаляете i -й элемент, массив элементов сокращается, а иногда вы ударяете объект, выходящий за границы массива. Рассмотрим этот сценарий:

  1. создать массив из 3 элементов
  2. итерация от 0 до 2, удаление i-го элемента
    1. i = 0, отметьте (i <3 элемента), удалите первый элемент, массив элементов сокращается до 2 (0, 1) </li>
    2. i = 1, проверка (i <2 элемента) удаляет первый элемент, массив элементов сокращается до 1 (0), но удаляется только второй элемент, поэтому 0-й элемент остается от предыдущей итерации (то есть 1-го элемента из оригинального набора). </li>

Это могло бы объяснить "странный путь".

...