解决圆角离屏渲染方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决圆角离屏渲染方案相关的知识,希望对你有一定的参考价值。

最近看了大量的优化tableview方案,为了配合sd下载图片,并且解决圆角图片离屏渲染问题,于是利用category自己写了个处理圆角的方法,解决了离屏渲染问题(并不是非常高效,感觉只是降低了GPU的消耗,但是提升了CPU的消耗,但是好歹也算是能提高一点fps),我还是更推荐使用yyimage下载图片,里面封装了处理圆角图片方法。

下面是代码:

//
//  UIImageView+CornerRadius.m
//  test
//
//  Created by gkoudai_xsm on 16/4/11.
//  Copyright © 2016年 gkoudai_xsm. All rights reserved.
//
#import <objc/runtime.h>
#import "UIImageView+CornerRadius.h"

static NSString * const kIsRounding = @"kIsRounding";
static NSString * const kHadAddObserver = @"kHadAddObserver";
static NSString * const kProcessedImage = @"kProcessedImage";


@interface UIImageView ()

//在category里添加属性  自己实现get和set方法  objc_getAssociatedObject/objc_setAssociatedObject
@property (nonatomic ,assign)BOOL isRounding;
@property (nonatomic ,assign)BOOL hadAddObserver;

@end

@implementation UIImageView (CornerRadius)
//public method
- (instancetype)initWithRoundingRectImageView{
    self = [super init];
    if (self) {
        [self roundingRect];
    }
    return self;
}

- (void) roundingRect {
    
    self.isRounding = YES;
    if (!self.hadAddObserver) {
        //添加个kvo
        [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
        
        self.hadAddObserver = YES;
    }
}

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:@"image"]) {
        UIImage *newImage = change[NSKeyValueChangeNewKey];
        if ([newImage isMemberOfClass:[NSNull class]]) { //判断是否为空
            return;
            
        } else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
            //新图 判断处理
            return;
        }
        if (self.isRounding) {
            
            [self roundingRectWithImage:newImage cornerRadius:self.frame.size.width/2];
        }
    }
}

#pragma mark - 处理图片
- (void)roundingRectWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius {
    
    CGSize size = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
    
    // //获得用来处理图片的图形上下文,设置no为不透明
    UIGraphicsBeginImageContextWithOptions(size, NO, scale);
    
    if (nil == UIGraphicsGetCurrentContext()) {
        return;
    }
    //针对某个角画圆形区域
    UIBezierPath *roundingPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:cornerRadii];
    // 添加裁剪
    [roundingPath addClip];
    // 边框线宽
    roundingPath.lineWidth = 0.1;
    
    [image drawInRect:self.bounds];
    // 开始画
    [roundingPath stroke];
    
    //从当前上下文中获取一个UIImage对象
    UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
    
    //关闭图形上下文
    UIGraphicsEndImageContext();
    
    //关联一个处理的图片
    objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    self.image = processedImage;
}

#pragma mark - Property

- (BOOL)hadAddObserver {
    
    return [objc_getAssociatedObject(self, &kHadAddObserver) boolValue];
}

- (void)setHadAddObserver:(BOOL)hadAddObserver {
    
    objc_setAssociatedObject(self, &kHadAddObserver, @(hadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)isRounding {
    return [objc_getAssociatedObject(self, &kIsRounding) boolValue];
}

- (void)setIsRounding:(BOOL)isRounding {
    objc_setAssociatedObject(self, &kIsRounding, @(isRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark - dealloc
- (void)dealloc{
    
    if (self.hadAddObserver) {
        
        [self removeObserver:self forKeyPath:@"image"];
    }
    
}
@end

 

以上是关于解决圆角离屏渲染方案的主要内容,如果未能解决你的问题,请参考以下文章

iOS沉思录UIImage圆角矩形的‘离屏渲染’和‘在屏渲染’实现方法

iOS圆角的离屏渲染,你真的弄明白了吗

如何高性能的给 UIImageView 加个圆角?

swift 给UIView添加圆角,避免离屏渲染

离屏渲染

Swift高效设置圆角图片的方法