Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIGraphicsBeginImageContext Deprecated #984

Open
zhuwo opened this issue Jun 14, 2023 · 8 comments
Open

UIGraphicsBeginImageContext Deprecated #984

zhuwo opened this issue Jun 14, 2023 · 8 comments

Comments

@zhuwo
Copy link

zhuwo commented Jun 14, 2023

大佬,我们这边使用了您的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了,

image

大佬是否需要更新下

@w1090485608
Copy link


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);

@CodeSlaveZhang
Copy link

如果不想像上面一样处理
可以在

  • (void)_displayAsync:(BOOL)async
    这个函数里面添加
    if (self.bounds.size.width<=0 || self.bounds.size.height<=0) {
    self.contents = nil;
    return;
    }

wjiuxing pushed a commit to wjiuxing/YYText that referenced this issue Oct 19, 2023
…CGBitampContext: size={382, 0}. Use UIGraphicsImageRenderer to avoid this assert.
wjiuxing pushed a commit to wjiuxing/YYText that referenced this issue Oct 19, 2023
…CGBitampContext: size={382, 0}. Use UIGraphicsImageRenderer to avoid this assert.
wjiuxing added a commit to wjiuxing/YYText that referenced this issue Oct 19, 2023
…CGBitampContext: size={382, 0}. Use UIGraphicsImageRenderer to avoid this assert.
wjiuxing added a commit to wjiuxing/YYText that referenced this issue Oct 19, 2023
…CGBitampContext: size={382, 0}. Use UIGraphicsImageRenderer to avoid this assert.
wjiuxing added a commit to wjiuxing/YYText that referenced this issue Oct 20, 2023
…CGBitampContext: size={382, 0}. Use UIGraphicsImageRenderer to avoid this assert.
lyb5834 added a commit to lyb5834/YYText that referenced this issue Oct 23, 2023
@wanghaolyj
Copy link

如果不想像上面一样处理 可以在

  • (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

@ZackDT
Copy link

ZackDT commented Nov 2, 2023

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()
    }
}

}
`

EchoLunar pushed a commit to EchoLunar/YYText that referenced this issue Nov 23, 2023
@lizhi0123
Copy link

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()
        }
    }
}


@zhoumingwu
Copy link

It seems like the master has retired from the scene for many years. It's unlikely that he will make a comeback again

@NubiaYin
Copy link

这个API还能继续用,只不过当layer的width或height 为0时会触发断言,否则不会。
这个场景在使用AutoLayout时比较常见。

@MonicaZhou
Copy link

如果不想像上面一样处理 可以在

* (void)_displayAsync:(BOOL)async
  这个函数里面添加
  if (self.bounds.size.width<=0 || self.bounds.size.height<=0) {
  self.contents = nil;
  return;
  }

最低支持iOS9的代码,得用这个~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants