Open zhuwo opened 1 year ago
将 UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale); CGContextRef context = UIGraphicsGetCurrentContext(); if (self.opaque) { CGSize size = self.bounds.size; size.width = self.contentsScale; size.height = self.contentsScale; CGContextSaveGState(context); { if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) { CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height)); CGContextFillPath(context); } if (self.backgroundColor) { CGContextSetFillColorWithColor(context, self.backgroundColor); CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height)); CGContextFillPath(context); } } CGContextRestoreGState(context); } task.display(context, self.bounds.size, ^{return NO;}); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); self.contents = (__bridge id)(image.CGImage);
替换为 UIGraphicsImageRendererFormat *format = [[UIGraphicsImageRendererFormat alloc] init]; format.opaque = self.opaque; format.scale = self.contentsScale;
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:self.bounds.size format:format];
UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
CGContextRef context = rendererContext.CGContext;
if (self.opaque) {
CGSize size = self.bounds.size;
size.width *= self.contentsScale;
size.height *= self.contentsScale;
CGContextSaveGState(context); {
if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
if (self.backgroundColor) {
CGContextSetFillColorWithColor(context, self.backgroundColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
} CGContextRestoreGState(context);
}
task.display(context, self.bounds.size, ^{return NO;});
}];
self.contents = (__bridge id)(image.CGImage);
如果不想像上面一样处理 可以在
如果不想像上面一样处理 可以在
- (void)_displayAsync:(BOOL)async 这个函数里面添加 if (self.bounds.size.width<=0 || self.bounds.size.height<=0) { self.contents = nil; return; }
@implementation YYTextAsyncLayer(Hook)
(void)load { Method a = class_getInstanceMethod(self, @selector(display)); Method b = class_getInstanceMethod(self, @selector(swizzing_display)); method_exchangeImplementations(a, b); }
(void)swizzing_display{ //通过变量名称获取类中的实例成员变量 if (self.bounds.size.width<=0 || self.bounds.size.height<=0) { self.contents = nil; return; } else { [self swizzing_display]; } }
@end
It's better to do this
Swift的话,采用上面一样的hook方法,在appdelegate方法中调用 YYTextAsyncLayer.swizzleDisplay
` import YYText /// 避免iOS17的崩溃 extension YYTextAsyncLayer {
static let swizzleDisplay: Void = {
let originalSelector = #selector(display)
let swizzledSelector = #selector(swizzing_display)
guard let originalMethod = class_getInstanceMethod(YYTextAsyncLayer.self, originalSelector),
let swizzledMethod = class_getInstanceMethod(YYTextAsyncLayer.self, swizzledSelector) else {
return
}
method_exchangeImplementations(originalMethod, swizzledMethod)
}()
@objc func swizzing_display() {
if bounds.size.width <= 0 || bounds.size.height <= 0 {
contents = nil
return
} else {
swizzing_display()
}
}
} `
I do not want to change code in pods. so I create two classe. PPYYLabel, PPYYTextAsyncLayer . user PPYYLabel replace YYLabel
import Foundation
import YYText
///PPYYLabel 代替YYLabel ios17崩溃修复
class PPYYLabel: YYLabel{
override class var layerClass: AnyClass {
return PPYYTextAsyncLayer.self
}
}
import Foundation
import YYText
/// ios17崩溃修复
class PPYYTextAsyncLayer: YYTextAsyncLayer {
override func display() {
if self.bounds.size.width<=0 || self.bounds.size.height<=0 {
self.contents = nil
return
} else {
print("---- bounds.width = , ",self.bounds.size.width , " ,height = ",self.bounds.size.height)
super.display()
}
}
}
It seems like the master has retired from the scene for many years. It's unlikely that he will make a comeback again
这个API还能继续用,只不过当layer的width或height 为0时会触发断言,否则不会。 这个场景在使用AutoLayout时比较常见。
如果不想像上面一样处理 可以在
* (void)_displayAsync:(BOOL)async 这个函数里面添加 if (self.bounds.size.width<=0 || self.bounds.size.height<=0) { self.contents = nil; return; }
最低支持iOS9的代码,得用这个~
大佬,我们这边使用了您的YYText,发现在iOS 17上运行会崩溃,触发了系统的断言: UIGraphicsBeginImageContext() failed to allocate CGBitampContext: size={382, 0}, scale=3.000000, bitmapInfo=0x2002. Use UIGraphicsImageRenderer to avoid this assert.
查了下 api,发现UIGraphicsBeginImageContext在iOS 17上已经deprecated了,
大佬是否需要更新下