注册
iOS

Xcode15Beta填坑-修复YYLabel的Crash问题

前言


趁着版本空隙,升级到了Xcode15-Beta2本想提前体验下iOS17。本以为这次升级Xcode能直接运行应该没什么大问题,没曾想到一运行后程序直接Crash了,Crash是在YYLabel下的YYAsyncLayer类里面。众所周知,YYLabel是由远古大神ibireme开发的YYKit下属的组件。已经多年没有适配了,但是依然老当益壮,只有部份由于Api变更导致的问题需要简单维护即可。以下就是此次问题定位与修复的全过程。


Crash定位


此次升级后编译我司项目,直接Crash,Crash日志如下。


8db5dbd38fec9f369e4862ddba94fd55.png


Crash是在YYTextAsyncLayer类下面的第193行代码如下:


UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale);


其实第一眼看代码崩溃提示就很明显了,这次Xcode15在UIGraphicsBeginImageContextWithOptions下面加了断言,如果传入的size width 或者 height其中一个为0,会直接return 返回断言。并且提示我们升级Api为UIGraphicsImageRenderer可以解决此问题。


本着探究的精神,我重新撤回用Xcode14.3.1编译,看为什么不会崩溃,结果其实也会报Invalid size警告但是不会崩溃,警告如下。


a26ea2efae2d0a2022493e503911a520.png


解决方案


我们使用UIGraphicsImageRenderer替代老旧的UIGraphicsBeginImageContextWithOptions(其实早已标记为过时),实测即使size为 zero,UIGraphicsImageRenderer在Xcode15下依然会渲染出一个zero size的Image,但是这毫无意义,所以我们简单判断一下,如果是非法的size我们直接retrun,代码如下:


从193行开始一直替换到self.contents = xxx。为止,即可解决此次问题。


if (self.bounds.size.width < 1 || self.bounds.size.height < 1) {

CGImageRef image = (__bridge_retained CGImageRef)(self.contents);

self.contents = nil;

if (image) {

CFRelease(image);

}

return;

}

UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:self.bounds.size];

UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {

if (self.opaque) {

if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) {

CGContextSetFillColorWithColor(context.CGContext, [UIColor whiteColor].CGColor);

[context fillRect:self.bounds];

}

if (self.backgroundColor) {

CGContextSetFillColorWithColor(context.CGContext, self.backgroundColor);

[context fillRect:self.bounds];

}

}

task.display(context.CGContext, self.bounds.size, ^{return NO;});

}];

self.contents = (__bridge id)(image.CGImage);


结尾


以上就是Xcode15修复UIGraphicsBeginImageContextWithOptions由于加了断言导致的Crash问题。我也强烈建议各位有时间检查项目其他代码直接升级成UIGraphicsImageRenderer的方案。如果确实没时间,要加上如下判断,防止Crash。由于我是在Debug上必崩,如果是断言问题Release不一定会有事,但是还是建议大家修改一下。


if (self.size.width < 1 || self.size.height < 1) {

return nil;

}

作者:jerryfans
链接:https://juejin.cn/post/7250288616534261797
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册