liuzhiyi1992/ZYCornerRadius

设置圆角图片闪退

shenshangjimiaoZG opened this issue · 36 comments

[self.headerImg sd_setImageWithURL:[NSURL URLWithString:customer.headimg] placeholderImage:[UIImage imageNamed:@"icon_lxr"]];
会有闪退的现象。

能否add一个all exceptions 断点看看闪在哪里

我这边复现不了,朋友那边是否有demo?

检查下bad_sccess当次的KVO是否合法,再者得到的newImage是否合法

没有,是个大项目

这个情况出现不多,但不知道为什么出现

现在还有办法重现吗?想看看控制台

测试了很多次,好像重复不了

好吧 : (

猜测不知道是否imageView被释放了

 我也估计是释放了 0x108a9fa9b <+261>: movq 0x21a576(%rip), %rsi ; "release"

2016-05-03 10 03 01

我重现了,但是控制台没有任何东西打印 @liuzhiyi1992

感觉是ImageView在活动期间被释放了,有什么办法重现的?我这边想调调

self.headerImg.layer.cornerRadius=25;
self.headerImg.layer.masksToBounds = YES;
//[self.headerImg zy_cornerRadiusAdvance:25 rectCornerType:UIRectCornerAllCorners];

我把你的代码屏蔽后就没有问题了

肯定的,ZYCornerRadius处理图片切角过程中可能项目中对象控制问题而操作到空指针对象了,如果这是个demo我可以帮助你找出问题

空指针对象?可是我打印过,没有空指针对象

如果方便的话,可以检查下UIGraphicsGetImageFromCurrentImageContext返回nil的当次,的image对象是否有问题(value 和 class),还有是否操作不在主线程中进行?

我发现要的圆角的图片 size是0

  • (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType

    CGSize size = self.bounds.size; 这个是会导致崩溃?size为0 @liuzhiyi1992

size为零切圆角会不成功,应该不会crash,试试看看size为0那个位置的image参数是否合法

size为0的那次调用应该不是导致crash那次,imageView在被layout之前size是0没问题

if(size.height==0||size.width==0)
{
CGSize temp=size;
temp.height=25;
temp.width=25;
size=temp;
}
我把代码改了后,反复测试就没有问题了。 @liuzhiyi1992

用masonry布局,这个有影响?我修改了那个size,就不会出现崩溃了,

用masonry的确会出现size为0的情况,不过我这边试过写死size为0也不会造成影响,朋友那边做了什么修改不崩?

  • (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
    CGSize size = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
    if(size.height==0||size.width==0)
    {
    CGSize temp=size;
    temp.height=25;
    temp.width=25;
    size=temp;
    }
    UIGraphicsBeginImageContextWithOptions(size, NO, scale);
    if (nil == UIGraphicsGetCurrentContext()) {
    return;
    }
    UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
    [cornerPath addClip];
    [image drawInRect:self.bounds];
    [self drawBorder:cornerPath];
    UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    self.image = processedImage;
    }
    就修改了这个方法,然后反复测试都没有问题了

恩恩你是给了个size,但是图片size变了就不好办了。你可以size为零时让他return试试,等有size了他会再进来的。

使用masonry,不改size,那这个 [self.headerImg zy_cornerRadiusAdvance:25 rectCornerType:UIRectCornerAllCorners]; 方法是要放到-(void)layoutSubviews吗?我之前都是在初始化写的。

在什么地方都可以,不用放在layoutSubviews哦,你可以看到在源代码里有个方法validateFrame,当size为0时(未布局),会在下次布局(size非0时)时再做圆角处理。

刚才说的你可以加一个size为零时的return,是为了试试能不能解决朋友那边的崩溃问题

为零是不行的。

为零时当次不会切角,会放在下次layout成功后切角

这是最终修改好的,不会再崩溃了。
谢谢你终极关怀。

#pragma mark - Kernel
/**

  • @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered
    */

    • (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {

    CGSize size = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
    if(size.height==0||size.width==0)
    {
    CGSize temp=size;
    temp.height=25;
    temp.width=25;
    size=temp;

    CGRect rect=self.bounds;
    rect.size=temp;
    self.bounds=rect;
    

    }
    UIGraphicsBeginImageContextWithOptions(size, NO, scale);
    if (nil == UIGraphicsGetCurrentContext()) {
    return;
    }
    UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
    [cornerPath addClip];
    [image drawInRect:self.bounds];
    [self drawBorder:cornerPath];
    UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    self.image = processedImage;
    }

/**

  • @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers
    */

    • (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor {

    CGSize size = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
    if(size.height==0||size.width==0)
    {
    CGSize z=size;
    z.height=25;
    z.width=25;
    size=z;

    CGRect rect=self.bounds;
    rect.size=z;
    self.bounds=rect;
    

    }
    UIGraphicsBeginImageContextWithOptions(size, YES, scale);
    if (nil == UIGraphicsGetCurrentContext()) {
    return;
    }
    UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
    UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
    [backgroundColor setFill];
    [backgroundRect fill];
    [cornerPath addClip];
    [image drawInRect:self.bounds];
    [self drawBorder:cornerPath];
    UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    self.image = processedImage;
    }

A piece of cake

只是不能用pod update了,你以后更新了,俺还得改,哈哈。

后期我留意下这个问题的出现

@liuzhiyi1992 我只所以出现以上问题,是因为在一个app我先用一个角色登录一个主页面,里面测试网络加载,退出后再用另一个角色登录后另一个主页面就出现上述问题了。

我这遇到有关圆角处理的闪退,特定机型上必现。
CGSize size = image.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
[path addClip];
[image drawAtPoint:CGPointZero];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

崩溃发生在addClip这个方法。处理了一张1.5M的jpg图片。估计是因为重绘过程处理图片内存太大导致。系统也抓不到崩溃日志。准备换方式实现啦。