Fuerza NSMenu (submenú anidado) actualización para menú principal de la aplicación de cacao

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

  •  19-09-2019
  •  | 
  •  

Pregunta

  1. Tengo algunas submenú inserta como elemento de submenú Ventana de menú principal
  2. Tengo una instancia de mi objeto (vamos a suponer su nombre de clase es MenuController) heredados de NSObject y soportes 2 de métodos NSMenuDelegate: - numberOfItemsInMenu: - Menú: updateItem: atIndex: shouldCancel:
  3. Esta instancia añadido como Blue-objeto en SEMILLA para despertar en tiempo de ejecución
  4. Objeto de los pasos 2-3 configurados como delegado de submenú (paso 1)

Ahora, puedo proporcionar el contenido de submenú en tiempo de ejecución.

A continuación, hacer lo siguiente: Me puede añadir nuevos elementos o eliminar edad de una matriz (en el interior MenuController que contiene los títulos de menú) que asigna al submenú real a través de protocolo y delegado. Todo funciona bien. Excepto una cosa: me gusta asignar accesos directos a mis elementos de menú dinámicos. CMD-1, CMD-2, CMD-3, etc

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

Por lo tanto, para llamar a algunos artículos que no quiero ir a la ventana / MySubMenu / myItem hacer clic en él con el ratón, lo que quiero de prensa sólo un acceso directo, como CMD-3 a llamar el artículo.

Ok, periódicamente funciona como se esperaba. Pero, en general, no tengo manera de informar a Menú Principal de mis cambios submenú anidado, excepto que se abre la ventana / MySubMenu para recargar su contenido. Una forma estable para reproducir el problema - sólo tratar de eliminar algún elemento y pulse el acceso directo antiguo asignado a ella, después de crear nuevo artículo como reemplazar por borrada - bingo - acceso directo no funcionará antes de navegar a la ventana / MySubMenu para ver el contenido submenú actual .

No sé una manera de forzar menú principal para reconstruir sus submenús ... Probé: [[NSApp mainMenu] Actualización] y juegos con NSNotificationCenter para enviar NSMenuDidAddItemNotification, NSMenuDidRemoveItemNotification, NSMenuDidChangeItemNotification

He intentado salida a mi submenú y llamo para actualizar el método de forma explícita - no hay manera ... Algunas veces AppKit llamadas de mis métodos de delegado - y veo que, a veces no quiere llamar a cualquier cosa. Parece que una estrategia aleatoria.

¿Cómo puedo estar seguro de que después de "que algunos llaman" mi submenú estará en el estado actual después de las modificaciones internas de la matriz?

¿Fue útil?

Solución

Para implementar 1: 1 de mapeo, implementar en delegado estos 3 métodos:

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

y

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

y

- (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 - es var interna de tipo NSMenu *

A continuación, cuando la fuerza quiere actualizar el submenú, en cualquier momento - sólo llamar

[self menuNeedsUpdate:nil];

Otros consejos

  

He intentado: [[NSApp mainMenu] Actualización] ...

Usted está en el camino correcto. Esta puede ser la situación en la que uno se justifica una matriz paralela en una aplicación Cocoa.

  1. Mantenga una matriz mutable de elementos de menú, en paralelo a la matriz de modelo de objetos que representan los elementos de menú.
  2. Cuando reciba numberOfItemsInMenu:, comparar el número de modelo de objetos que tiene a la cuenta de la matriz elementos de menú. Si es menor, utilice el método removeObjectsInRange: para acortar la matriz elementos de menú. Si es más, la almohadilla de la matriz con NSNull objetos. (No se puede utilizar nil aquí, ya que un NSArray sólo puede contener objetos, y nil es la ausencia de un objeto.)
  3. Cuando reciba menu:updateItem:atIndex:shouldCancel:, sustituya el objeto de la matriz en la que el índice de con el nuevo elemento de menú antes de devolver el nuevo elemento de menú
  4. Conforme al protocolo NSMenuValidation, como se menciona en la documentación para el método update . En el método de validación, encontrar el índice de la opción de menú dentro de la matriz , a continuación, obtener el objeto del modelo de ese índice en el modelo de objetos de matriz y actualizar el elemento del menú de la misma. Si estás en Snow Leopard, puede enviar el menú de la opción de menú de un mensaje de propertiesToUpdate para determinar qué valores de propiedad que necesita para conferir a partir del objeto modelo.

La advertencia es que este objeto, el delegado del menú, también debe ser el objetivo de los elementos del menú. Estoy asumiendo que es. Si no es así, se producirá un error en el paso # 4, ya que los mensajes de validación se envían a los objetivos de los artículos de menú.

Es posible que desee presentar una solicitud de mejora pidiendo una mejor manera.

En la llamada delegado de numberOfItemsInMenu: llamada removeAllItems ... es bastante extraño, pero de lo contrario el menú no se actualiza, incluso lo esta llamando a un delegado

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

    [menu removeAllItems];

    return [self.templateURLs count] + 2;

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top