2010-07-14 21 views
8

UIMenuController'ı dinamik bir menü için kullanmaya çalışıyorum (başlıklar ve eylemler bir sunucudan geliyor). Sorun şu ki UIMenuItems initWithTitle: action: action'ın bir @selector olduğunu kullanmam gerekiyor.@selector ve dinamik yöntemler ile Dinamik UIMenuItems

@selector (gönderme :) 'yi kullanabilirim ancak daha sonra kullanıcının hangi öğelerin basıldığını ayırt edemiyorum. - (void) gönderme: (id) gönderen {NSLog (@ "% @", gönderen); } UIMenuController olduğunu ve hangi menü maddesine basıldığını anlatacak bir yöntemi olmadığını söyledi.

Mümkün olan her seçiciyi göndermek için 100 yöntem yazamam, tamam 10'dan sonra olmayacak ama yine de bu iyi bir fikir gibi görünmeyecek.

Bu gibi her seçici için dinamik yöntemler oluşturmalı mıyım? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html? Bu da tuhaf görünüyor.

Bu iki daha iyi önermeler o zaman?

// Bu yaklaşım işe yaramıyor.

- (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 
} 

// Bu yaklaşım gerçekten çok çirkin.

- (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]; } 

cevap

10

Bu yaklaşım işe yarar, her düğme için benzersiz bir seçici adına ihtiyaç duyarsınız ve bu addan hedeflemek istediğiniz her şeye bir eşleme gerekir.
Seçici adı için benzersiz bir dizgenin seçilmesi gerekir (UUID'ler veya belki de bir sanitized & başlığın önekli sürümü çalışır). menü öğesiyle ilişkili hangi URL

- (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 
    } 
} 

Şimdi iletici bakabilirsiniz:

- (void)forwarder:(UIMenuController *)mc { 
    NSLog(@"URL for item is: %@", [actionDict objectForKey:_cmd]); 
} 
Sonra çağrıyı ve farklı selektör isimlerle "takma" bunu çözer tek yöntem gerekir

gibi bir şey kullanabilirsiniz seçicileri oluşturmak için:

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

_cmd nereden geliyor ve nedir? – Jeena

+2

@jen: Uygulama işlevinin çağrıldığı seçici için bir anahtar sözcük. NSStringFromSelector (_cmd) 'yi günlüğe kaydetmeyi deneyin. –

+1

Awesome work Guys, Çok teşekkür ederim. – sachin

0

menü öğeleri aynı şeyi sürece, neden bir işlemi paylaşmalıyım? Devam edip, istediğiniz bir davranışı belirleyen ve menü öğelerini bunlara bağlayan eylemler yazarım.

+1

sorun derleme zamanında olacak hangi işlemlerin bilmiyor olmasıdır eylemleri olacak c çünkü Bir sunucudan ome, her zaman menü için bir başlık ve kullanıcı klick üzerine tıkladığında çağrılması gereken bir http-url. Soruyu bazı kodlarla güncelleyeceğim. – Jeena