美文网首页
iOS中如何在恰当的时机隐藏键盘

iOS中如何在恰当的时机隐藏键盘

作者: 小冰山口 | 来源:发表于2023-11-18 20:25 被阅读0次

    还是可恶的网易七鱼SDK
    接上篇

    当我要 present一个SDKviewController时, 就是前面提到的QYSessionViewController, 不知道怎么搞的, 这个viewController会默认弹出键盘, 这就很影响用户体验了, 本来你是隐式地弹出这个viewController, 让用户无法察觉, 然后在这个被拉起的viewController中成功地创建会话, 然后隐式地发出消息. 键盘突然闪一下算怎么回事呢?

    所以我的思路是:

    最开始的时候, 我觉得应该是在键盘即将弹出的时候, 隐藏键盘. 发现不行
    然后我的思路是, 在键盘的frame即将发生变化的时候, 隐藏键盘, 发现还是不行, 键盘依然弹出

    最后发现, 必须在textDidBeginEditingNotification的时候去隐藏键盘, 才可以

    最后发现, 其调用顺序是:
    UITextView.textDidBeginEditingNotification -> UITextView.keyboardWillChangeFrameNotification -> UITextView.keyboardWillShowNotification

            NotificationCenter.default.also { it in
                it.addObserver(self, selector: #selector(hideKeyboard(noti:)), name: UITextView.textDidBeginEditingNotification, object: nil)
            }
    
            NotificationCenter.default.also { it in
                it.addObserver(self, selector: #selector(hideKeyboard(noti:)), name: UITextView.keyboardWillChangeFrameNotification, object: nil)
            }
    
            NotificationCenter.default.also { it in
                it.addObserver(self, selector: #selector(hideKeyboard(noti:)), name: UITextView.keyboardWillShowNotification, object: nil)
            }
    

    也就是说, 要在发出UITextView.textDidBeginEditingNotification这个通知之后隐藏键盘才是最及时的, 这个时候, 隐藏键盘是不会弹出键盘的, 其余两个, 及时写了隐藏键盘的代码, 键盘也还是会弹出, 让用户感知到

    因为我用的是第三方, 所以我隐藏键盘的代码是:

    IQKeyboardManager.shared().resignFirstResponder()
    

    另一个需要注意的问题是, 通知监听和取消监听的时机, 因为最开始的时候, 我是在viewDidLoad监听和viewDidDisappear取消监听的, 这就会造成一个问题, 因为我这个viewController是一个webView的容器, 所以大部分的跳转都其实是H5的跳转, 所以这样一来, 并没有起到相应的想过, 相反, 在很多不需要隐藏键盘的H5界面, 键盘都隐藏了, 因为它们的容器是监听了通知, 当收到UITextView.textDidBeginEditingNotification这个通知之后隐藏键盘. 所以我把监听的通知放在了调用方法之中.

        /// 发送客服自定义消息
        func sendCustomMessage(dict: Dictionary<String, Any?>) {
            NotificationCenter.default.also { it in
                it.addObserver(self, selector: #selector(hideKeyboard(noti:)), name: UITextView.textDidBeginEditingNotification, object: nil)
            }
            
            if let productDict = dict["productDetail"] as? Dictionary<String, Any>,
               let product = JSONDeserializer<CustomServiceProduct>.deserializeFrom(dict: productDict)
            {
                let commodityInfo = QYCommodityInfo()
                commodityInfo.show = product.show
                commodityInfo.cardType = product.cardType
                commodityInfo.title = product.title
                commodityInfo.desc = product.desc
                commodityInfo.note = product.note
                commodityInfo.pictureUrlString = product.picture
                commodityInfo.urlString = product.url
                commodityInfo.actionText = product.actionText
                commodityInfo.goodsId = product.goodsId
                commodityInfo.goodsCId = product.goodsCId
                commodityInfo.orderId = product.orderId
                commodityInfo.actionTextColor = UIColor.cp_text()
                // TODO: - 这里的逻辑很奇葩, 这个会话是和控制器耦连的, 所以控制器如果没有push或者present出来, 会话是无法真正连接的
                // TODO: - 所以思路就是创建会话, 并present出来, 但用户感知不到, 给客服发消息, 然后dissmiss掉会话
                // 创建一个与客服的回话
                let session = QYSDK.shared().sessionViewController()
                // 文档上说要包在nav中使用, 那就勉强包一下吧
                // 不知道包含了什么骚操作
                // 创建一个空的控制器, 他的view在屏幕之外, 就是不让用户看到
                let vc = UIViewController()
                vc.view.frame = CGRectMake(0, UIScreen.main.bounds.size.height + 100, 1, 1)
                // 然后把这个控制器的view, 添加在当前控制器的view上
                view.addSubview(vc.view)
                guard let session = session else { return }
                let nav = UINavigationController(rootViewController: session)
                // 设置模态的类型, 如果按照默认, 会有动画效果, 就会被看出来
                nav.modalPresentationStyle = .overCurrentContext
                // 空的控制器, 将nav模态出来
                vc.present(nav, animated: false) {
                    // 模态出来之后, 延时1.5秒操作, 这里的时间无法把控, 之前设置过1s, 但是, 仍有可能会话没有连接成功
                    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.5) {
                        // 延时1.5s后, 会话连接成功(其实也不一定)后, 发送消息给客服
                        session.sendCommodityInfo(commodityInfo)
                        // 然后再过0.25秒, 将会话控制器dismiss掉, 全程不让用户感知
                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) {
                            session.dismiss(animated: false) {
                                NotificationCenter.default.also { it in
                                    it.removeObserver(self, name: UITextView.textDidBeginEditingNotification, object: nil)
                                }
                            }
                        }
                    }
                }
            }else {
                
            }
            callback(with: .Success, method: .SendCustomMessage)
        }
    

    方法开始时, 监听通知, 当sessionViewController弹出之后, 成功发送消息, sessionViewControllerdismiss掉之后, 取消通知. 这样就不会干扰到其他H5的界面了.

    相关文章

      网友评论

          本文标题:iOS中如何在恰当的时机隐藏键盘

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