Blur / Unblur作为协议扩展

时间:2017-03-30 15:35:04

标签: ios swift protocols blur uivisualeffectview

我创建了 Blurable 协议,扩展程序具有模糊功能。

protocol Blurable {}

extension Blurable where Self: UIView {

    func blur(with effect:  UIBlurEffectStyle) {
        let blurEffect = UIBlurEffect(style: effect)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)

        blurEffectView.frame = bounds
        addSubview(blurEffectView)
    }
}

现在我要添加 unblur 功能。 如果它是一个类我将 blurEffectView 作为类属性并创建 unblur 函数,如下所示:

func unblur() {
    blurEffectView.removeFromSuperview
}

由于协议扩展不允许存储属性,这个问题的正确解决方案是什么?

2 个答案:

答案 0 :(得分:1)

您可以在协议声明中保留变量。

protocol Blurable: class {
    var blurEffectView: UIVisualEffectView? { set get }

    func applyBlur(with effect: UIBlurEffectStyle)
    func removeBlur() 
}

private var xoAssociationKey: UInt8 = 0

extension Blurable where Self: UIView {

    // If you want to avoid adding "blurEffectView" to each UIView class, 
    // you can do it this way
    var blurEffectView: UIVisualEffectView? {
        get {
            return objc_getAssociatedObject(self, &xoAssociationKey) as? UIVisualEffectView
        }

        set(newBlurEffectView) {
            objc_setAssociatedObject(self, &xoAssociationKey, newBlurEffectView, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
    }

    func applyBlur(with effect: UIBlurEffectStyle) {
        let blurEffect = UIBlurEffect(style: effect)
        blurEffectView = UIVisualEffectView(effect: blurEffect)

        blurEffectView?.frame = bounds

        if let blurEffectView = blurEffectView { addSubview(blurEffectView) }
    }

    func removeBlur() {
        if let blurEffectView = blurEffectView {
            blurEffectView.removeFromSuperview()
        }

        blurEffectView = nil
    }
}

这应该有效。您可以将blurEffectView保持为非可选变量,但此解决方案在将来的更改中更安全有效,因为您可以以编程方式检查是否应用了模糊。

var someView = SomeView()

if let _ = someView.blurEffectView {
    print("YEAP")
} else {
    print("NOPE")
}

答案 1 :(得分:0)

我用过这个 -

extension UIView {
    func blur() {
        let blurEffect = UIBlurEffect(style: .light)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = self.bounds
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.addSubview(blurEffectView)
    }

    func unBlur() {
        for subview in self.subviews {
            if subview is UIVisualEffectView {
                subview.removeFromSuperview()
            }
        }
    }
}

您还可以添加标记并通过检查其标记来删除视图,但我觉得这是一个更好的选择。也可以使用扩展程序here