Blur/Unblur 作为协议扩展的功能
Blur/Unblur function as a protocol extension
我创建了 Blurable 协议,其扩展名具有 blur 功能。
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 功能。
如果它是 class,我会将 blurEffectView 作为 class 属性 并创建 unblur 函数像这样:
func unblur() {
blurEffectView.removeFromSuperview
}
由于协议扩展不允许存储属性,这个问题的正确解决方案是什么?
您可以在协议声明中保留变量。
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")
}
我用过这个-
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.
我创建了 Blurable 协议,其扩展名具有 blur 功能。
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 功能。 如果它是 class,我会将 blurEffectView 作为 class 属性 并创建 unblur 函数像这样:
func unblur() {
blurEffectView.removeFromSuperview
}
由于协议扩展不允许存储属性,这个问题的正确解决方案是什么?
您可以在协议声明中保留变量。
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")
}
我用过这个-
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.