本来 UIMenuController 这个东西挺简单的.
直到…
遇到 InputView, 我就醉了, 程序也崩溃了.
这里以 Demo 为主, 来说明问题.
实现的效果很简单, 如下图
ViewController.m
#import "ViewController.h"
@interface ViewController ()
// 罪魁祸首在这里
@property (nonatomic, strong) UIView *inputView;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self config];
}
// 这个方法必须重写, 否则不显示菜单
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)config
{
CGRect inputFrame = CGRectMake(100, 200, 200, 100);
_inputView = [[UIView alloc] initWithFrame:inputFrame];
[self.view addSubview:_inputView];
CGRect bFrame = CGRectMake(100, 120, 120, 60);
UIButton *btn = [[UIButton alloc] initWithFrame:bFrame];
btn.backgroundColor = [UIColor greenColor];
btn.titleLabel.font = [UIFont systemFontOfSize:14.f];
btn.layer.borderWidth = 1.f;
btn.layer.cornerRadius = 5.f;
btn.layer.masksToBounds = YES;
btn.layer.borderColor = [UIColor redColor].CGColor;
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn setTitle:@"点我弹出菜单" forState:UIControlStateNormal];
btn.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(onTap:)];
[btn addGestureRecognizer:tap];
[self.view addSubview:btn];
}
- (void)onTap:(UITapGestureRecognizer *)recognizer
{
// 写与不写, 暂时没有发现有什么卵用
[self becomeFirstResponder];
UIMenuController *menu = [UIMenuController sharedMenuController];
UIMenuItem *delete = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteBtnClick)];
NSArray *array = [NSArray arrayWithObjects:delete, nil];
[menu setMenuItems:array];
[menu setTargetRect:recognizer.view.frame inView:recognizer.view.superview];
[menu setMenuVisible:YES animated:YES];
}
- (void)deleteBtnClick
{
NSLog(@"tap the delete menu item");
}
@end
在 iOS8 | iOS9 上面运行起来, 就 crash.
但是 iOS7 就安然无事.
crash 信息大概这个样子
Terminating app due to uncaught exception ‘UIViewControllerHierarchyInconsistency’,
reason: ‘child view controller: should have parent view controller: but requested parent is:’
最终找到问题在于, 声明并使用了一个全局 inputView.
注意, 不添加该 InputView, 也不会有问题, 即注释下面代码
[self.view addSubview:_inputView];
查阅文档知道, 从 iOS8 起, 需要检查 InputView 不应该有父视图.
可以看看, UIKit 里面的 inputView
解决方案
1.将原来的 inputView 改个名字.
2.不要使用全局变量 InputView.