Força NSMenu (submenu aninhado) atualização para Menu Principal do Cacau App

StackOverflow https://stackoverflow.com/questions/2232476

  •  19-09-2019
  •  | 
  •  

Pergunta

  1. Eu tenho alguns submenu inserido como Janela submenu item Menu Principal
  2. Eu tenho uma instância de meu objeto (vamos supor que seu nome de classe é MenuController) herdada de NSObject e suportes 2 de métodos NSMenuDelegate: - numberOfItemsInMenu: - Menu: UpdateItem: atIndex: shouldCancel:
  3. Esta instância adicionado como Blue-objeto em NIB para despertar em tempo de execução
  4. objecto de passos 2-3 configurado como delegado para submenu (passo 1)

Agora, eu posso fornecer conteúdo submenu em tempo de execução.

Em seguida, eu seguinte: Eu posso adicionar novos itens ou remover velho de uma matriz (dentro MenuController que contém títulos de menu) que mapeado para submenu real via protocolo e delegado. Tudo funciona muito bem. Exceto uma coisa: Eu gosto de atalhos atribuir a meus itens de menu dinâmico. CMD-1, CMD-2, CMD-3, etc

Janela / MySubMenu / MyItem1 CMD-1, MyItem2 CMD-2, ...

Assim, para chamar alguns itens que eu não quero ir à janela / MySubMenu / MyItem clicar nele com o mouse, eu quero pressionar apenas um atalho, como CMD-3 para ligar para o item.

Ok, periodicamente, ele funciona como esperado. Mas, geralmente, eu não tenho nenhuma maneira de informar Menu Principal sobre as minhas alterações submenu aninhado, a não ser abrir a janela / MySubMenu para recarregar seu conteúdo. Uma maneira estável para reproduzir o problema - apenas tentar remover algum item e pressione o atalho antigo atribuído a ele, depois de criar novo item como substituir para eliminada - bingo - não vai funcionar atalho antes de navegar para Janela / MySubMenu para ver o conteúdo submenu atual .

Eu não sei uma maneira de forçar menu principal para reconstruir seus submenus ... Eu tentei: [[NSApp mainMenu] update] e jogos com NSNotificationCenter para enviar NSMenuDidAddItemNotification, NSMenuDidRemoveItemNotification, NSMenuDidChangeItemNotification

Eu tentei tomada ao meu submenu e chamada para método de atualização explicitamente - não há nenhuma maneira ... Algumas vezes AppKit chama meus métodos de delegado - e vejo que, às vezes ele não quer chamar qualquer coisa. Looks como uma estratégia aleatória.

Como posso ter certeza de que depois de "alguns chamam de" meu submenu estará em estado real após modificações da matriz internos?

Foi útil?

Solução

Para implementar o mapeamento 1: 1, em implementar delegado estes métodos 3:

- (BOOL)menu:(NSMenu *)menu
updateItem:(NSMenuItem *)item 
atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel

e

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

e

- (void)menuNeedsUpdate:(NSMenu *)menu
{
    if (!attachedMenu)
        attachedMenu = menu;
    if (!menu)
        menu = attachedMenu;
    NSInteger count = [self numberOfItemsInMenu:menu];
    while ([menu numberOfItems] < count)
        [menu insertItem:[[NSMenuItem new] autorelease] atIndex:0];
    while ([menu numberOfItems] > count)
        [menu removeItemAtIndex:0];
    for (NSInteger index = 0; index < count; index++)
        [self menu:menu updateItem:[menu itemAtIndex:index] atIndex:index shouldCancel:NO];
}

attachedMenu - é var interna do tipo NSMenu *

Em seguida, quando você quer forçar atualizar o submenu, a qualquer hora - basta chamar

[self menuNeedsUpdate:nil];

Outras dicas

Eu tentei: [[NSApp mainMenu] update] ...

Você está no caminho certo. Esta pode ser a única situação em que uma matriz paralela em um aplicativo de cacau é garantido.

  1. Mantenha uma matriz mutável de itens de menu, paralela à sua matriz de objetos modelo que os itens do menu representam.
  2. Quando você receber numberOfItemsInMenu:, comparar o número de modelo de objetos que você tem que a contagem da matriz os itens do menu. Se é menor, uso o método removeObjectsInRange: para encurtar a matriz os itens do menu. Se for mais, almofada da matriz com NSNull objetos. (Você não pode usar nil aqui, uma vez que um NSArray só pode conter objetos e nil é a ausência de um objeto.)
  3. Quando você receber menu:updateItem:atIndex:shouldCancel:, substituir o objeto na matriz em que índice com o novo item de menu antes de retornar o novo item de menu
  4. conformidade com o protocolo NSMenuValidation, como mencionado em a documentação para o método update. No seu método de validação, encontrar o índice do item de menu dentro da matriz , em seguida, obter o objeto modelo em que o índice no modelo de objetos de matriz e atualizar o item de menu a partir dele. Se você está no Snow Leopard, você pode enviar de menu do item de menu a mensagem propertiesToUpdate para determinar que valores propriedade que você precisa para conferir a partir do modelo de objeto.

A ressalva é que este objeto, o delegado do menu, também deve ser o alvo dos itens do menu. Estou assumindo que ele é. Se não for, este irá falhar na etapa # 4, como as mensagens de validação são enviados para alvos os itens do menu.

Você pode querer arquivar uma solicitação de melhoria pedindo uma maneira melhor.

Na chamada delegado para numberOfItemsInMenu: chamada removeAllItems ... é muito estranho, mas o resto do menu não atualizar, mesmo que está chamando para um delegado

- (NSInteger)numberOfItemsInMenu:(NSMenu*)menu {

    [menu removeAllItems];

    return [self.templateURLs count] + 2;

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top