2010-07-14 14 views
8

Ich versuche, UIMenuController für ein dynamisches Menü zu verwenden (Titel und Aktionen kommen von einem Server). Das Problem ist, dass ich UIMenuItems initWithTitle verwenden muss: action: wobei action ein @selector ist.Dynamische UIMenuItems mit @selector und dynamischen Methoden

Ich kann @selector (Versand :) verwenden, aber ich kann nicht unterscheiden, welche der Elemente der Benutzer gedrückt hat. - (void) dispatch: (id) Absender {NSLog (@ "% @", Absender); } sagt, es ist ein UIMenuController und es gibt keine Methode, die sagen würde, welcher Menüpunkt gedrückt wurde.

Ich kann nicht nur 100 Methoden schreiben, um jeden möglichen Selektor zu versenden, ok, es wird nicht mehr als 10 sein, aber trotzdem scheint das keine gute Idee zu sein.

Muss ich für jeden dieser Selektoren dynamische Methoden erstellen? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html? Das scheint auch seltsam.

Gibt es bessere Vorschläge als diese beiden?

// Dieser Ansatz funktioniert nicht.

- (void)showMenu { 

    [self becomeFirstResponder]; 

    NSMutableArray *menuItems = [[NSMutableArray alloc] init]; 

    UIMenuItem *item; 
    for (MLAction *action in self.dataSource.actions) { 
     item = [[UIMenuItem alloc] initWithTitle:action.title action:@selector(action:)]; 
     [menuItems addObject:item]; 
     [item release]; 
    } 

    UIMenuController *menuController = [UIMenuController sharedMenuController]; 
    menuController.menuItems = menuItems; 
    [menuItems release]; 
    [menuController update]; 
    [menuController setMenuVisible:YES animated:YES]; 

} 

- (void)action:(id)sender { 
    NSLog(@"%@", sender); // gives UIMenuController instead of UIMenuItem 
    // I can not know which menu item was pressed 
} 

// Dieser Ansatz ist wirklich hässlich.

- (void)showMenu { 

    [self becomeFirstResponder]; 

    NSMutableArray *menuItems = [[NSMutableArray alloc] initWithCapacity:5]; 

    UIMenuItem *item; 
    NSInteger i = 0; 
    for (MLAction *action in self.dataSource.actions) { 
     item = [[UIMenuItem alloc] initWithTitle:action.text 
                      action:NSSelectorFromString([NSString stringWithFormat:@"action%i:", i++])]; 
     [menuItems addObject:item]; 
     [item release]; 
    } 

    UIMenuController *menuController = [UIMenuController sharedMenuController]; 
    menuController.menuItems = menuItems; 
    [menuItems release]; 
    [menuController update]; 
    [menuController setMenuVisible:YES animated:YES]; 

} 

- (void)action:(NSInteger)number { 
    NSLog(@"%i", number); // gives the index of the action in the menu. 
} 

// This is a hack, I have to assume that there will never be more then 15 actions 
- (void)action0:(id)sender { [self action:0]; } 
- (void)action1:(id)sender { [self action:1]; } 
- (void)action2:(id)sender { [self action:2]; } 
- (void)action3:(id)sender { [self action:3]; } 
- (void)action4:(id)sender { [self action:4]; } 
- (void)action5:(id)sender { [self action:5]; } 
- (void)action6:(id)sender { [self action:6]; } 
- (void)action7:(id)sender { [self action:7]; } 
- (void)action8:(id)sender { [self action:8]; } 
- (void)action9:(id)sender { [self action:8]; } 
- (void)action10:(id)sender { [self action:10]; } 
- (void)action11:(id)sender { [self action:11]; } 
- (void)action12:(id)sender { [self action:12]; } 
- (void)action13:(id)sender { [self action:13]; } 
- (void)action14:(id)sender { [self action:14]; } 

Antwort

10

Dieser Ansatz würde funktionieren, obwohl Sie einen eindeutigen Selector-Name für jede Schaltfläche und eine Zuordnung von diesem Namen zu dem, was Sie möchten, benötigen.
Für den Namen des Selektors muss eine eindeutige Zeichenkette gewählt werden (UUIDs oder eine vorbereitete Version des Titels funktionieren möglicherweise mit einer bereinigten &). Dann brauchen Sie eine Methode, die den Anruf und „alias“ es mit den verschiedenen Selektornamen löst:

- (void)updateMenu:(NSArray *)menuEntries { 
    Class cls = [self class]; 
    SEL fwd = @selector(forwarder:); 
    for (MenuEntry *entry in menuEntries) { 
     SEL sel = [self uniqueActionSelector]; 
     // assuming keys not being retained, otherwise use NSValue: 
     [self.actionDict addObject:entry.url forKey:sel]; 
     class_addMethod(cls, sel, [cls instanceMethodForSelector:fwd], "[email protected]:@"); 
     // now add menu item with sel as the action 
    } 
} 

Jetzt ist der Spediteur kann nachschauen, welche URL mit dem Menüpunkt zugeordnet ist:

- (void)forwarder:(UIMenuController *)mc { 
    NSLog(@"URL for item is: %@", [actionDict objectForKey:_cmd]); 
} 

die Selektoren generieren Sie so etwas wie verwenden:

- (SEL)uniqueActionSelector { 
    NSString *unique = ...; // the unique part 
    NSString *selString = [NSString stringWithFormat:@"menu_%@:", unique]; 
    SEL sel = sel_registerName([selString UTF8String]); 
    return sel; 
} 
+0

Woher kommt die _cmd und was ist das? – Jeena

+2

@jen: Ein Schlüsselwort für den Selektor, mit dem die Implementierungsfunktion aufgerufen wird. Versuchen Sie, 'NSStringFromSelector (_cmd)' zu protokollieren. –

+1

Super Arbeit Jungs, vielen Dank. – sachin

0

Es sei denn, die Menüpunkte, die gleiche Sache zu tun, warum sollte sie eine Aktion teilen? Ich würde fortfahren und Aktionen schreiben, die ein gewünschtes Verhalten spezifizieren und die Menüpunkte mit denen verbinden.

+1

Das Problem ist, dass ich nicht, welche Aktionen es sein wird, bei der Kompilierung, da die Aktionen wissen kann, wird c Bei einem Server handelt es sich immer um einen Titel für das Menü und eine http-URL, die aufgerufen werden soll, wenn der Benutzer darauf klickt. Ich werde die Frage mit einem Code aktualisieren. – Jeena

Verwandte Themen