// TODO: -开篇
- 什么场景会遇到什么问题(这篇文章需要解决的)
- 设计的原则
- 解释过程
- 总结
协议部分
public protocol MaskableProtocol: AnyObject {
var maskableHelper: MaskableHelper { get set }
func showMaskIfPossible()
func hideMaskIfPossible()
}
协议的默认实现
private var gestureMaskViewKey: UInt8 = 0
private var maskableHelperKey: UInt8 = 0
public extension MaskableProtocol where Self: UIView {
private var gestureMaskView: UIView? {
get {
return objc_getAssociatedObject(self, &gestureMaskViewKey) as? UIView
}
set {
objc_setAssociatedObject(self, &gestureMaskViewKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var maskableHelper: MaskableHelper {
get {
return objc_getAssociatedObject(self, &maskableHelperKey) as? MaskableHelper ?? MaskableHelper()
}
set {
objc_setAssociatedObject(self, &maskableHelperKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func showMaskIfPossible() {
guard gestureMaskView == nil, let superview = self.superview else { return }
UIView.performWithoutAnimation {
gestureMaskView = UIView()
gestureMaskView?.backgroundColor = UIColor(white: 0, alpha: 0.5)
let tap = UITapGestureRecognizer(target: maskableHelper, action: #selector(maskableHelper.executeMaskAction))
gestureMaskView?.addGestureRecognizer(tap)
superview.insertSubview(gestureMaskView!, belowSubview: self)
guard let maskView = gestureMaskView else { return }
maskView.frame = superview.bounds
}
}
func hideMaskIfPossible() {
self.gestureMaskView?.removeFromSuperview()
self.gestureMaskView = nil
}
}
这里在extension
中给UIView设置了两个关联对象
,分别是:
gestureMaskView: UIView
- 作用:添加到目标view的superview上,用于响应手势事件
maskableHelper: MaskableHelper
- 作用:由于swift的extension中不支持运行时,无法直接使用Selector,需要借助一个类来中转Action
借助一个辅助类
public class MaskableHelper: NSObject {
var maskAction: (() -> Void)?
init(action: (() -> Void)? = nil) {
self.maskAction = action
super.init()
}
@objc func executeMaskAction() {
maskAction?()
}
}
应用
让需要作用的UIView遵守MaskableProtocol
,并初始化一个MaskableHelper
class ContentInputView, MaskableProtocol {
// MARK: - Lazy Loading
internal lazy var maskableHelper: MaskableHelper = {
let helper = MaskableHelper()
helper.maskAction = { [weak self] in
guard let `self` = self else { return }
self.hideMaskIfPossible()
self.endEditing(true)
}
return helper
}()
}
下需要显示Mask的时候调用协议中的func showMaskIfPossible( )
即可
// MARK: - KeyboardObserving
func keyboardWillShow(notification: Notification) {
self.replyInputView.showMaskIfPossible()
if let height = notification.keyboardSize?.height, let duration = notification.keyboardAnimationDuration {
UIView.animate(withDuration: duration) {
self.replyInputView.willAscend()
self.replyInputView.snp.updateConstraints { make in
make.bottom.equalToSuperview().offset(-height)
}
self.view.layoutSubviews()
}
}
}
关键词
关联对象
协议
协议的默认实现