UIImageView设置圆角不触发离屏渲染的方法

来源:互联网 发布:韩国人种相貌 知乎 编辑:程序博客网 时间:2024/06/06 19:05

众所周知,如果使用以下的两行代码设置图像圆角,是会触发离屏渲染(离屏渲染详解)。

imageView.layer.cornerRadius = 10  imageView.layer.masksToBounds = true

如果是在一个tableview中,每一个cell有这样一个圆角图片,那么在滚动时肯定会严重掉帧。所以以上的方法只适合在静态界面(不需要滚动交互)中使用,或者在当前页面中只有一个圆角图片时。

那如果需要在tableview中设置多个圆角图片呢?既然我们要避免让GPU触发离屏,那么只能把兵符交给CPU,虽然CPU对图形的处理能力不及GPU,但由于这种处理的难度不大,且代价肯定远小于上下文切换。具体方法是在给UIImageView赋值UIImage时,将UIImage进行裁剪再赋值。不多说了,上代码:

import UIKitextension UIImageView {    private struct aKey {        static var imageObserverKey = "imageObserver"    }    var aCornerRadius:CGFloat {        get {            return self.imageObserver().cornerRadius        }        set {            self.imageObserver().cornerRadius = newValue        }    }    private func imageObserver() -> XYImageObserver{        var observer = objc_getAssociatedObject(self, &aKey.imageObserverKey) as? XYImageObserver        if observer == nil {            observer = XYImageObserver.init(imageView: self)            objc_setAssociatedObject(self, &aKey.imageObserverKey, observer, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)        }        return observer!;    }}// MARK: - extension UIImageextension UIImage {    private struct aKey {        static var aCornerRadiuskey = "aCornerRadius"    }    var aCornerRadius:Bool {        get {            if let value = objc_getAssociatedObject(self, &aKey.aCornerRadiuskey) as? Bool {                return value            } else {                return false            }        }        set {            objc_setAssociatedObject(self, &aKey.aCornerRadiuskey, newValue as Bool, .OBJC_ASSOCIATION_COPY_NONATOMIC)        }    }}// MARK: - 监听者class XYImageObserver: NSObject {    var originImageView:UIImageView!    var originImage:UIImage?    var cornerRadius:CGFloat{        willSet {            if self.cornerRadius != newValue {                self.cornerRadius = newValue                if newValue > 0 {                    self.cutImageView()                }            }        }    }    init(imageView:UIImageView) {        self.cornerRadius = 0        super.init()        self.originImageView = imageView        // 添加监听        imageView.addObserver(self, forKeyPath: "image", options: .new, context: nil)    }    // 监听回调    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {        if keyPath == "image" {            if let newImage = change?[NSKeyValueChangeKey.init(rawValue: "new")] {                if (newImage as AnyObject).isKind(of:UIImage.classForCoder()) == false || ((newImage as? UIImage)?.aCornerRadius)! {                    return                }                if self.originImageView.aCornerRadius > 0 {                    self.cutImageView()                }            }        }    }    // 裁剪图片    private func cutImageView() {        if let image = self.originImageView.image {            self.originImage = image            // 开始裁剪            UIGraphicsBeginImageContextWithOptions(self.originImageView.bounds.size, false, UIScreen.main.scale)            let currentContext = UIGraphicsGetCurrentContext()            let path = UIBezierPath.init(roundedRect: self.originImageView.bounds, cornerRadius: self.cornerRadius).cgPath            currentContext?.addPath(path)            currentContext?.clip()            if currentContext != nil {                self.originImageView.layer.render(in: currentContext!)                let image = UIGraphicsGetImageFromCurrentImageContext()                UIGraphicsEndImageContext()                if image?.isKind(of:UIImage.classForCoder()) == true {                    image?.aCornerRadius = true;                    self.originImageView.image = image;                } else {                    DispatchQueue.main.async {                        self.cutImageView()                    }                }            }        }    }    deinit {        self.originImageView.removeObserver(self, forKeyPath: "image")    }}
0 0
原创粉丝点击