美文网首页
iOS 键盘和UIMenuController的并存问题

iOS 键盘和UIMenuController的并存问题

作者: 且行且珍惜_iOS | 来源:发表于2020-03-10 14:26 被阅读0次

    问题描述

    当UITextView 处于编辑状态时,即键盘存在时,UITextView是第一响应者,而当需要弹出UIMenuController时,第一响应者需要变更为处理UIMenuController菜单事件的对象,此时UITextView就不是第一响应者,键盘就会隐藏,造成键盘和UIMenuController不能同时出现。问题示意图如下:

    键盘和UIMenuController不能同时出现效果预览

    解决方案

    史上最详细的iOS之事件的传递和响应机制-原理篇
    iOS响应链全家桶

    此方案是通过改变响应链来解决的,如果对响应链不了解的先去补一下这方面的知识。

    在保证UITextView第一响应者的前提下,我们可以覆盖改变UITextView的nextResponder,让nextResponder指向UIMenuController菜单事件的执行者;同时也要注意,在UIMenuController隐藏后,要取消nextResponder指向,不改变原有的响应链。

    
    @interface SLTextView : UITextView
    //覆盖下一个响应者
    @property (nonatomic, weak) UIResponder *overrideNextResponder; 
    @end
    @implementation SLTextView
    
    - (UIResponder *)nextResponder {
        if(_overrideNextResponder == nil){
            return [super nextResponder];
        } else {
            return _overrideNextResponder;
        }
    }
    // UIMenuController 菜单可以执行操作
    - (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
        if (_overrideNextResponder != nil) {
            return NO;
        }
        return [super canPerformAction:action withSender:sender];
    }
    @end
    
    
    
    //长按显示菜单 UIMenuController
    - (void)longPressShowMenuView:(UILongPressGestureRecognizer *)longPress {
        //编辑过程中,self.textView是第一响应者
        if(self.textView.isFirstResponder){
            //如果textView是第一响应者,则对titleLabel进行响应链透传,覆盖self.textView的下一个响应者
            self.textView.overrideNextResponder = self.titleLabel;
            //添加菜单隐藏的监听,当菜单隐藏时,要重置self.textView.overrideNextResponder = nil
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuViewDidHide:) name:UIMenuControllerDidHideMenuNotification object:nil];
        }else {
            //如果当前无第一响应者,就成为第一响应者
            [self.titleLabel becomeFirstResponder];
        }
        
        UIMenuController *menuController = [UIMenuController sharedMenuController];
        UIMenuItem *saveItems = [[UIMenuItem alloc] initWithTitle:@"保存" action:@selector(save:)];
        UIMenuItem *noteItem = [[UIMenuItem alloc] initWithTitle:@"笔记" action:@selector(note:)];
        menuController.menuItems = @[noteItem, saveItems];
        if (@available(iOS 13.0, *)) {
            [menuController showMenuFromView:self.view rect:self.titleLabel.frame];
        } else {
            [menuController setTargetRect:self.titleLabel.frame inView:self.view];
            [menuController setMenuVisible:YES animated:YES];
        }
    }
    
    // 隐藏菜单UIMenuController的通知
    - (void)menuViewDidHide:(NSNotification*)notification {
        //重置,不影响原有的响应链
        self.textView.overrideNextResponder = nil;
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidHideMenuNotification object:nil];
    }
    
    
    键盘和UIMenuController并存问题解决

    iOS_Tips 不定时更新,已有示例 : 1、暗黑模式 2、AppleID登录应用 3、AVFoundation 高仿微信相机拍摄和编辑 4、AVFoundation 人脸检测 5、AVFoundation 实时滤镜 6、GPUImage框架的使用 7、VideoToolBox和AudioToolBox音视频编解码 8、OpenGL ES学习 9、LeetCode算法练习 10、键盘和UIMenuController的并存问题。。。。。

    如果需要跟我交流的话:
    ※ Github: https://github.com/wsl2ls
    ※ 简书:https://www.jianshu.com/u/e15d1f644bea

    相关文章

      网友评论

          本文标题:iOS 键盘和UIMenuController的并存问题

          本文链接:https://www.haomeiwen.com/subject/wkoidhtx.html