【Swift4.2】利用运行时给UIView写延展筛选面板

需求

  • 在做项目的时候,有一个开发需求类似做一个京东物品筛选的一个功能,在这个功能的开发过程中,怎么想一个一劳永逸的方式解决这个效果。

开发设计

  • 在开发这个界面的时候我们是这个的,筛选面板中的视图,我们是不可能一劳永逸的,每个开发需求都是不一样的,定制化的东西计较多,所以我们没有办法一劳永逸的界面,我们唯一能一劳永逸的地方是,这个左滑的动画以及遮罩层点击的点击事件,点击消失这个动作我们可以构思一下怎么解决,以后只要有左滑出界面的功能开发我们都可以调用一个方法轻松解决左滑,以及点击遮罩消失这个功能

开发代码

首先我们给UIView写一个延展,暴露出两个方法来控制显示和隐藏(具体实现请看代码注释),我们都知道iOS是不允许在延展中写属性的,只能写方法,那我们用到遮罩层怎么创建呢,别急:我们这里是用iOS的运行时(RunTime)来创建属性的

var lz_keyWindowOne = "lz_keyWindowOne"
var lz_maskViewOne = "lz_maskViewOne"
var lz_containerViewOne = "lz_containerViewOne"
var containerViewWidth = 270
let AnimateDuration = 0.35;
extension UIView {
    /// 这个方法只是用来获取单例KeyWindow
   private var lz_keyWindow : UIView! {
        get{
            /// 这个地方就是利用运行时来获取KeyWidow
            var keyWindow = objc_getAssociatedObject(self, &lz_keyWindowOne) as? UIView
            if keyWindow == nil {
                // 如果没有就获取KeyWindow
                keyWindow = UIApplication.shared.keyWindow
            }
            return keyWindow!
        }
    }
    /// 这个是我们创建遮罩的视图
   private var lz_maskView : UIView! {
        get{
            /// 这个地方就是利用运行时来获取遮罩视图(第一次肯定没有)需要创建
            var mask = objc_getAssociatedObject(self, &lz_maskViewOne) as? UIView
            if mask == nil {
                // 创建遮罩视图
                mask = UIView(frame: UIScreen.main.bounds)
                mask!.backgroundColor = UIColor(white: 0, alpha: 0.3)
                mask!.isUserInteractionEnabled = true
                // 在遮罩层上添加点击手势
                let tap = UITapGestureRecognizer(target: self, action: #selector(lz_cancelAction))
                mask!.addGestureRecognizer(tap)
                /// 这个地方就是利用运行时来存储遮罩视图 那上边下一次取的时候就有值了
                objc_setAssociatedObject(self, &lz_maskViewOne, mask, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            return mask!
        }
    }
    
    /// 这个是我们创建容器视图
    private var lz_containerView : UIView! {
        get{
            /// 这个地方就是利用运行时来获取容器视图 第一次肯定没有)需要创建
            var container = objc_getAssociatedObject(self, &lz_containerViewOne) as? UIView
            if container == nil {
                // 创建容器视图
                container = UIView()
                container!.backgroundColor = UIColor.white
                /// 这里是把你的筛选视图添加到容器视图上
                container!.addSubview(self)
                self.frame =  CGRect(x: 0, y: 0, width: containerViewWidth, height: Int(UIScreen.main.bounds.size.height))
                container!.frame.size = CGSize(width: CGFloat(containerViewWidth), height: UIScreen.main.bounds.size.height)
                /// 这个地方就是利用运行时来存储容器视图 那上边下一次取的时候就有值了
                objc_setAssociatedObject(self, &lz_containerViewOne, container, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            return container!
        }
    }
    
    /// 这里是暴露在外的方法(只要调用此方法就能显示)
   open func lz_showInWindowWithRight(){
    /// 这里需要注意的是遮罩视图和容器视图一定放keyWindow 上的要不会有bug
        self.lz_keyWindow.addSubview(self.lz_maskView)
        self.lz_keyWindow.addSubview(self.lz_containerView)
        self.lz_maskView.alpha = 0.0
        self.lz_containerView.frame.x = UIScreen.main.bounds.size.width
    /// 这里做左滑的动画
        UIView.animate(withDuration: AnimateDuration) {
            self.lz_maskView.alpha = 1
            self.lz_containerView.frame.x = UIScreen.main.bounds.size.width - CGFloat(containerViewWidth)
        }
    }
    /// 遮罩视图上的点击事件
  @objc private func lz_cancelAction(){
        lz_dismissFromWindow()
    }
    /// 隐藏筛选视图
    func lz_dismissFromWindow(){
        UIView.animate(withDuration: AnimateDuration, animations: {
            self.lz_maskView.alpha = 0.0
            self.lz_containerView.frame.x = UIScreen.main.bounds.size.width
        }) { (finished) in
            self.lz_maskView.removeFromSuperview()
            self.lz_containerView.removeFromSuperview()
        }
    }
}

你可能感兴趣的:(筛选面板,Swift,Runtime)