2010-07-14 28 views
8

Tôi đang cố gắng sử dụng UIMenuController cho một menu động (tiêu đề và hành động đến từ một máy chủ). Vấn đề là tôi phải sử dụng UIMenuItems initWithTitle: action: nơi action là một @selector.UIMenuItems động với @selector và các phương thức động

Tôi có thể sử dụng @selector (dispatch :) nhưng sau đó tôi không thể phân biệt các mục mà người dùng đã nhấn. - (void) dispatch: (id) người gửi {NSLog (@ "% @", người gửi); } nói rằng nó là một UIMenuController và nó không có một phương pháp mà sẽ cho biết mục trình đơn đã được nhấn.

Tôi không thể chỉ viết 100 phương pháp để gửi mọi bộ chọn có thể, ok sẽ không có nhiều hơn sau đó 10 nhưng vẫn còn, điều này có vẻ không phải là một ý tưởng tốt.

Tôi có phải tạo phương pháp động cho từng bộ chọn như vậy không? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html? Điều này có vẻ kỳ lạ quá.

Bất kỳ đề xuất nào tốt hơn sau đó là hai?

// Cách tiếp cận này không hiệu quả.

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

// Cách tiếp cận này thực sự xấu.

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

Trả lời

10

Cách tiếp cận đó sẽ hoạt động, mặc dù bạn cần một tên bộ chọn duy nhất cho mỗi nút và ánh xạ từ tên đó đến bất kỳ thứ gì bạn muốn nhắm mục tiêu.
Đối với tên bộ chọn, một chuỗi duy nhất phải được chọn (UUID hoặc có thể là phiên bản tiền tố & được làm vệ sinh trước sẽ hoạt động). Sau đó, bạn cần một phương pháp mà giải quyết các cuộc gọi và "bí danh" nó với tên selector khác nhau:

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

Bây giờ ngành giao nhận có thể tra cứu những gì URL có liên quan đến các mục menu:

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

Để tạo bộ chọn bạn có thể sử dụng một cái gì đó như:

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

_cmd đến từ đâu và nó là gì? – Jeena

+2

@jen: Từ khóa cho bộ chọn có chức năng thực hiện được gọi. Thử đăng nhập 'NSStringFromSelector (_cmd)'. –

+1

Làm việc tuyệt vời Guys, Cảm ơn bạn rất nhiều. – sachin

0

Trừ các mục trong menu làm điều tương tự, tại sao nên họ chia sẻ một hành động? Tôi sẽ tiếp tục và viết các hành động chỉ định hành vi mà bạn muốn và liên kết các mục menu với những mục đó.

+1

Vấn đề là tôi không thể biết hành động sẽ có lúc biên dịch vì các hành động sẽ c ome từ một máy chủ, nó luôn luôn là một tiêu đề cho trình đơn và một http-url nên được gọi khi người dùng klicks trên đó. Tôi sẽ cập nhật câu hỏi với một số mã. – Jeena

Các vấn đề liên quan