iOS中将UIView事件跨层传递给VC

2023-06-21  本文已影响0人  Sweet丶

在iOS工程中,通常我们的详情页面UI都是比较复杂的,这就导致往往视图层级较深,这种情况下,如果要将内部的UIView识别到事件时,抛出到VC来执行具体处理,需要一层一层中转,很麻烦。

本文是介绍一种解决一层一层中转直达VC的方式。

一、问题引出

如下是一个打车软件的详情截图。我们分析页面,打赏司机按钮的层级结构: UIButton -》ZLToolView -》ZLHeaderView -》UITableView -》ZLContentView -》VC.view -》 VC。

龙背岭-东莞理工学院.jpeg
现在,如果我们点击打赏司机,需要VC去执行逻辑。
1. 不管是使用代理或者block,这个链路都很长。

这个事件首先是在ZLToolView添加按钮点击监听,然后需要中转回调给ZLHeaderView, 再回调给UITableView的父视图ZLContentView, 最后再回调给VC。

2. 使用全局通知

如果使用通知的话,能做到跨层,但是缺点是通知更适合于全局的一对多场景,一个UI事件还是一对一的关系; 此外过多的通知也不利于维护。

二、解决方案

上述问题我这边思考的一个解决方案是通过响应者链来实现从内层的View事件跨层抛给VC,理由如下:

具体的封装代码如下:

enum XLInnerViewEvent {
    case refreshABC // 刷新ABC
    case refreshDetail // 刷新详情接口,如果有参数,可以通过枚举关联值传递
}

protocol XLInnerEventResponsible: UIResponder {
    func innerEventHandle(type: XLInnerViewEvent)
}

extension UIView {
    // 一个沿着响应链向上传递事件的方法,bubble=冒泡
    func bubbleEvent(_ eventType: XLInnerViewEvent) {
        var nextRespnder = self.next
        while nextRespnder != nil {
            if let savior = nextRespnder as? XLInnerEventResponsible {
                savior.innerEventHandle(type: eventType)
                nextRespnder = nil
            }
            nextRespnder = nextRespnder?.next
        }
    }
}

使用:

// 内层view传递事件
@objc func reloadBtnAction() {
    self.bubbleEvent(.refreshABC)
}
// VC或响应链中感兴趣的类遵守协议XLInnerEventResponsible
extension VC: XLInnerEventResponsible {
    func innerEventHandle(type: XLInnerViewEvent) {
        switch type {
        case .refreshABC:
            print("refreshABC---")
        case .refreshDetail:
            print("refreshDetail---")
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读