iOS9之后圆角与阴影性能优化
2019-01-10 本文已影响0人
_码奴
圆角和阴影实现代码和各种实现方法对比都在下面,并且做了注释,可以查看注释了解差异和优劣
#import "ViewExtendController.h"
#import "UIImageView+DrawEx.h"
@interface ViewExtendController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,strong) UIImageView * imageView;
@property (nonatomic,strong) UIButton * button;
@property (nonatomic,strong) UITableView * tableView;
@end
@implementation ViewExtendController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"View扩展功能";
[self makeView];
}
- (void)makeView {
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 64, 100, 100)];
[self.view addSubview:self.imageView];
self.imageView.backgroundColor = [UIColor redColor];
self.imageView.layer.cornerRadius = 50;
// self.imageView.layer.masksToBounds = YES;
self.imageView.layer.shadowColor = UIColor.greenColor.CGColor;
self.imageView.layer.shadowOffset = CGSizeMake(3, 5);
self.imageView.layer.shadowRadius = 10;
self.imageView.layer.shadowOpacity = 0.7;
// 上面阴影代码会离屏渲染,加上下面这句不会离屏渲染
// 创建一个圆形贝塞尔曲线, 加上这句,视图不进行离屏渲染
/*
* 这个方法会检测出内存泄漏 CGPathCreateWithRoundedRect
* 但是实际应该没有影响,因为如果释放程序会立刻崩溃,感觉应该只是系统延迟释放了,所以才会检测出泄漏
*/
//UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:im.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:im.bounds.size];
// self.imageView.layer.shadowPath = path.CGPath;
// 这个方法会检测出内存泄漏,CGPathCreateWithRoundedRect(self.imageView.bounds, self.imageView.bounds.size.width, self.imageView.bounds.size.height, NULL); 所以保险起见这里改成上面的方式
[self.view addSubview:self.tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ViewExtendCell * cell = [tableView dequeueReusableCellWithIdentifier:@"ViewExtendCell" forIndexPath:indexPath];
for(UIImageView * im in cell.viewsArray) {
// masksToBounds iOS9 之后不会离屏渲染,对帧率影响不明显
// im.layer.cornerRadius = im.bounds.size.width/2;
// im.layer.masksToBounds = YES; // 这句,不离屏,但是还是会有额外渲染,因为毕竟要裁剪圆角,主要问题是不能显示阴影,因为阴影也会被裁减掉
im.image = [UIImage imageNamed:@"timg"];
// 这个方法可以对帧率影响不明显,并且能在实现圆角的情况下不影响阴影的显示
[im drawCornerRadius:im.frame.size.width/2]; //这个方法来自是定义的类别中,下面有给出代码
}
return cell;
}
- (UITableView *)tableView {
if(!_tableView) {
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 164, self.view.frame.size.width, self.view.frame.size.height - 164) style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.rowHeight = 60;
[self.tableView registerClass:[ViewExtendCell class] forCellReuseIdentifier:@"ViewExtendCell"];
}
return _tableView;
}
@end
@implementation ViewExtendCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self) {
[self makeCell];
}
return self;
}
- (void)makeCell {
NSMutableArray * viewArray = [[NSMutableArray alloc] init];
self.iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(20, 5, 50, 50)];
[self.contentView addSubview:self.iconImage];
self.iconImage_1 = [[UIImageView alloc] initWithFrame:CGRectMake(75, 5, 50, 50)];
[self.contentView addSubview:self.iconImage_1];
self.iconImage_2 = [[UIImageView alloc] initWithFrame:CGRectMake(130, 5, 50, 50)];
[self.contentView addSubview:self.iconImage_2];
self.iconImage_3 = [[UIImageView alloc] initWithFrame:CGRectMake(185, 5, 50, 50)];
[self.contentView addSubview:self.iconImage_3];
// self.iconImage_3.layer.cornerRadius = 10;
// self.iconImage_3.layer.masksToBounds = YES;
self.iconImage_4 = [[UIImageView alloc] initWithFrame:CGRectMake(240, 5, 50, 50)];
[self.contentView addSubview:self.iconImage_4];
// self.iconImage_4.layer.cornerRadius = 10;
// self.iconImage_4.layer.masksToBounds = YES;
self.iconImage.image = [UIImage imageNamed:@"timg"];
self.iconImage_1.image = [UIImage imageNamed:@"timg"];
self.iconImage_2.image = [UIImage imageNamed:@"timg"];
self.iconImage_3.image = [UIImage imageNamed:@"timg"];
self.iconImage_4.image = [UIImage imageNamed:@"timg"];
[viewArray addObject:self.iconImage];
[viewArray addObject:self.iconImage_1];
[viewArray addObject:self.iconImage_2];
[viewArray addObject:self.iconImage_3];
[viewArray addObject:self.iconImage_4];
for(UIImageView * im in viewArray) {
// masksToBounds iOS9 之后不会离屏渲染,对帧率影响不明显
// im.layer.cornerRadius = im.bounds.size.width/2;
// im.layer.masksToBounds = YES; // 这句,不离屏,但是还是会有额外渲染,因为毕竟要裁剪圆角,主要问题在于会影响阴影的显示
// iOS9之后还是会造成离屏渲染了,下面使用 layer.mask 会离屏渲染,并且太多会影响帧率
// UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:im.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:im.bounds.size];
// CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
// //设置大小
// maskLayer.frame = im.bounds;
// //设置图形样子
// maskLayer.path = maskPath.CGPath;
// im.layer.mask = maskLayer; // iOS9之后还是会造成离屏渲染了,
// 因为上面有圆形测试代码m,设置了masksToBounds,所以下面阴影其实看不到
// 直接使用这种阴影会离屏渲染,但是帧率影响不明显,
im.layer.shadowColor = UIColor.greenColor.CGColor;
im.layer.shadowOffset = CGSizeMake(3, 5);
im.layer.shadowRadius = 10;
im.layer.shadowOpacity = 0.7;
//上面代码,阴影离屏渲染不太影响帧率,但是会对GUP消耗很大,这可能是阴影过多卡顿的主要原因
// 创建一个圆形贝塞尔曲线, 加上这句,阴影不再进行离屏渲染,并且降低GPU的资源占用率
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:im.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:im.bounds.size];
im.layer.shadowPath = path.CGPath;
//这个方法会内存泄漏,使用上面方法 CGPathCreateWithRoundedRect(im.bounds, im.bounds.size.width, im.bounds.size.height, NULL);,但实际应该没有影响,只是被延迟释放了而已,为了保险还是使用上面方法
}
self.viewsArray = viewArray;
}
@end
下面是 "UIImageView+DrawEx.h" 类的代码,这个里面没写什么,依托于UIImage+Corner.h这个类
#import "UIImageView+DrawEx.h"
#import "UIImage+Corner.h"
@implementation UIImageView (DrawEx)
- (UIImage *)drawCornerRadius:(CGFloat)cornerRadius {
// 获取裁减成圆角的图片,并重新赋值给imageview的image
UIImage * image = [self.image drawCornerInRect:self.bounds cornerRadius:cornerRadius];
self.image = image;
return image;
}
@end
下面是 UIImage+Corner类代码实现,
#import "UIImage+Corner.h"
@implementation UIImage (Corner)
- (UIImage *)drawCornerInRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius {
UIImage * image = nil;
// 创建贝塞尔曲线对象
UIBezierPath * bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
// 开始设置绘图
UIGraphicsBeginImageContextWithOptions(rect.size, false, [UIScreen mainScreen].scale);
CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath);
CGContextClip(UIGraphicsGetCurrentContext());
// 调用绘制方法
[self drawInRect:rect];
// 绘制图片
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
// 获取绘制完成的image
image = UIGraphicsGetImageFromCurrentImageContext();
// 结束绘制
UIGraphicsEndImageContext();
return image;
}
@end