需求:
点击TableView的某一行,弹出菜单
解决方案:
好吧,确实挺简单的,用UIMenuController添加两个UIMenuItem不就好了吗?blabla就实现代码:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[self.view addSubview:self.tableView];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"tableView:didSelectRowAtIndexPath:(%li)", indexPath.row);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:cell.frame inView:cell.superview];
UIMenuItem *like = [[UIMenuItem alloc] initWithTitle:@"赞" action:@selector(like:)];
UIMenuItem *dislike = [[UIMenuItem alloc] initWithTitle:@"踩" action:@selector(dislike:)];
[menu setMenuItems:@[like, dislike]];
[menu setMenuVisible:YES animated:YES];
}
- (void)like:(id)sender
{
NSLog(@"like performed");
}
- (void)dislike:(id)sender
{
NSLog(@"dislike performed");
}
...
这时候我们发现点击TableView的某一行并不会弹出菜单。这不科学啊,UIMenuController不就是这么用的吗?出了问题要干嘛呢?对!看官方文档。先看看UIMenuController的介绍。
从这段介绍中我们隐约可以看出,UIMenuController使用了单例模式,它可以展示一个editing menu,这个menu大概包括了cut、copy、paste、delete、select等命令。UIResponder的canPerformAction:withSend: 方法与editing menu有关,实现了这个方法的responder可以enable/disable一些菜单命令。
好像有点头绪了,UIResponder不就是UITableView的祖先类嘛!我们不妨再看一下UIResponder的canPerformAction:withSend: 方法的介绍。讲了什么呢?如果responder实现了action,这个方法默认是返回YES的;否则会继续调用下一个responder的这个方法。可是我们明明实现了action啊,可是却不能显示呢!继续看,与canPerformAction:withSend: 还有一个很相似的方法(BOOL)canBecomeFirstResponder,通过文档可以知道,这个方法默认是返回NO的。一个responder只有从这个方法里返回YES才能成为first responder并且收到touch events和action messages。UIResponder的子类必须重载这个方法才能成为first responder。那就重载一下吧:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return YES;
}
重新run一下,ok,效果出来了:
至此,大功告成。