Xcode15Beta填坑-修复YYLabel的Crash问题

前言

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

Crash定位

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

11271688008651_.pic.jpg

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

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

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

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

11261688008538_.pic.jpg

解决方案

我们使用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);
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);
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;
}
if (self.size.width < 1 || self.size.height < 1) {



return nil;


}
if (self.size.width < 1 || self.size.height < 1) { return nil; }

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYDQYCyZ' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片