2010-07-14 45 views
8

我正在嘗試爲動態菜單(標題和動作來自服務器)使用UIMenuController。問題是我必須使用UIMenuItems initWithTitle:action:where action是一個@selector。使用@selector和動態方法的動態UIMenuItem

我可以使用@selector(dispatch :),但然後我無法區分哪些用戶按下的項目。 - (void)dispatch:(id)sender {NSLog(@「%@」,sender); }說這是一個UIMenuController,它沒有一個方法可以告訴哪個菜單項被按下。

我不能只寫100個方法來調度每個可能的選擇器,確定不會超過10個但仍然,這似乎不是一個好主意。

我是否必須爲每個這樣的選擇器創建動態方法? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html?這看起來也很奇怪。

那麼這兩個更好的命題呢?

//此方法不起作用。

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

//這種方法真的很難看。

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

回答

10

儘管每個按鈕都需要一個唯一的選擇器名稱,並且從該名稱到任何想要定位的對象都需要一個映射,該方法仍可行。
對於選擇器名稱,必須選擇一個唯一的字符串(UUID或可能是經過消毒的標題的前綴版本&)。然後,你需要能解決呼叫和「別名」它與不同的選擇名字的其中一個方法:

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

現在轉發器可以看一下什麼URL與菜單項關聯:

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

要生成,你可以使用類似的選擇:

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

_cmd從哪裏來?它是什麼? – Jeena 2010-07-14 20:58:40

+2

@jen:調用實現函數的選擇器的關鍵字。嘗試記錄'NSStringFromSelector(_cmd)'。 – 2010-07-14 21:06:39

+1

令人敬畏的工作夥計們,非常感謝。 – sachin 2013-01-30 06:41:01

0

除非菜單項做同樣的事情,爲什麼要他們共享一個動作?我會繼續編寫指定所需行爲的操作,並將菜單項鍊接到這些操作。

+1

的問題是,我不知道哪些行爲會出現在編譯時,因爲行動將ç從服務器開始,它總是一個菜單標題和一個http-url,當用戶點擊它時應該調用它。我會用一些代碼更新這個問題。 – Jeena 2010-07-14 20:40:34