美文网首页
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