Skip to content

Instantly share code, notes, and snippets.

@iamtchelo
Forked from oboje/UIVisualEffect.swift
Created August 6, 2017 22:14
Show Gist options
  • Select an option

  • Save iamtchelo/9a4581802daf61d9bf5a96017f5af4fe to your computer and use it in GitHub Desktop.

Select an option

Save iamtchelo/9a4581802daf61d9bf5a96017f5af4fe to your computer and use it in GitHub Desktop.
(Ab)using UIVisualEffectView effect settings
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
import ObjectiveC
let image = UIImage(named: "berlinerdom.jpg")!
let imageView = UIImageView(image: image)
imageView.frame.size.width = 540
imageView.frame.size.height = 363
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
effectView.frame.size.width = 540//360
effectView.frame.size.height = 363//242
effectView.center = imageView.center
imageView.addSubview(effectView)
PlaygroundPage.current.liveView = imageView
PlaygroundPage.current.needsIndefiniteExecution = true
func properties(_ instance: NSObject) {
var count = UInt32()
let classToInspect = type(of: instance)
let properties : UnsafeMutablePointer<objc_property_t?> = class_copyPropertyList(classToInspect, &count)
var propertyNames = [String]()
let intCount = Int(count)
for i in 0..<intCount {
let property : objc_property_t = properties[i]!
guard let propertyName = NSString(utf8String: property_getName(property)) as? String else {
debugPrint("Couldn't unwrap property name for \(property)")
break
}
let v = instance.value(forKey: propertyName)
print(v!)
propertyNames.append(propertyName)
}
free(properties)
print(propertyNames)
}
extension UIVisualEffectView {
fileprivate var filterLayer: CALayer? {
return layer.sublayers?.first
}
fileprivate var blurFilter: NSObject? {
return filterLayer?
.filters?.flatMap({ $0 as? NSObject })
.first(where: { $0.value(forKey: "name") as? String == "gaussianBlur" })
}
fileprivate var saturationFilter: NSObject? {
return filterLayer?
.filters?.flatMap({ $0 as? NSObject })
.first(where: { $0.value(forKey: "name") as? String == "colorSaturate" })
}
fileprivate var matrixFilter: NSObject? {
return filterLayer?
.filters?.flatMap({ $0 as? NSObject })
.first(where: { $0.value(forKey: "name") as? String == "colorMatrix" })
}
var blurRadius: CGFloat? {
get {
return blurFilter?.value(forKey: kCIInputRadiusKey) as? CGFloat
}
set {
blurFilter?.setValue(newValue, forKey: kCIInputRadiusKey)
}
}
var enableBlur: Bool {
get {
let dimLayer = layer.sublayers?.last?.opacity != 0
return blurRadius != 0 && dimLayer
}
set {
blurRadius = 0
layer.sublayers?.last?.opacity = newValue ? 1 : 0
}
}
/// the same as saturation amount 1
var enableSaturation: Bool {
get {
return saturationFilter?.value(forKey: "enabled") as? Bool ?? false
}
set {
saturationFilter?.setValue(newValue, forKey: "enabled")
}
}
var enableColorMatrix: Bool {
get {
return matrixFilter?.value(forKey: "enabled") as? Bool ?? false
}
set {
matrixFilter?.setValue(newValue, forKey: "enabled")
}
}
var saturationAmount: CGFloat? {
get {
return saturationFilter?.value(forKey: "inputAmount") as? CGFloat
}
set {
saturationFilter?.setValue(newValue, forKey: "inputAmount")
}
}
var scale: CGFloat? {
get {
return filterLayer?.value(forKey: "scale") as? CGFloat
}
set {
filterLayer?.setValue(newValue, forKey: "scale")
}
}
}
func animateScale() {
effectView.filterLayer?.removeAllAnimations()
effectView.enableSaturation = false
effectView.enableBlur = false
let anim = CABasicAnimation(keyPath: "scale")
anim.fromValue = 0.05
anim.toValue = 1
anim.duration = 5
anim.repeatCount = .infinity
effectView.scale = 1
effectView.filterLayer?.add(anim, forKey: "scale")
}
func animateBlur() {
effectView.filterLayer?.removeAllAnimations()
effectView.enableSaturation = false
effectView.scale = 1
effectView.enableBlur = false
CATransaction.begin()
CATransaction.setAnimationDuration(5)
var anim = CABasicAnimation(keyPath: "filters.gaussianBlur.inputRadius")
anim.fromValue = 30
anim.toValue = 0
anim.repeatCount = .infinity
effectView.filterLayer?.add(anim, forKey: "filters.gaussianBlur.inputRadius")
anim = CABasicAnimation(keyPath: "opacity")
anim.fromValue = 1
anim.toValue = 0
anim.repeatCount = .infinity
effectView.layer.sublayers?.last?.add(anim, forKey: "opacity")
CATransaction.commit()
}
func animateBlurUIKit() {
effectView.filterLayer?.removeAllAnimations()
UIView.animate(withDuration: 5, delay: 0, options: .repeat, animations: {
effectView.effect = nil
}, completion: nil)
}
func animateSaturation() {
effectView.filterLayer?.removeAllAnimations()
effectView.enableBlur = false
effectView.scale = 1
let anim = CABasicAnimation(keyPath: "filters.colorSaturate.inputAmount")
anim.fromValue = 0
anim.toValue = 1.8
anim.duration = 5
anim.repeatCount = .infinity
effectView.saturationAmount = 1.8
effectView.filterLayer?.add(anim, forKey: "filters.colorSaturate.inputAmount")
}
//animateScale()
//animateBlur()
//animateBlurUIKit()
//animateSaturation()
effectView.enableSaturation = false
effectView.scale = 0.5
effectView.blurRadius = 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment