Skip to content

ios14YYAnimatedImageView图片显示问题 #573

Open
@afskalsfk

Description

@afskalsfk

ios14重写displayLayer方法后不再默认调用super

  • (void)displayLayer:(CALayer *)layer {
    if (_curFrame) {
    layer.contents = (__bridge id)_curFrame.CGImage;
    }else {
    if (@available(iOS 14.0, *)) {
    [super displayLayer:layer];
    }
    }
    }
    网上看到的资料解释为这样
    四、可能原因分析
    如果iOS14-beta版本,在有重写- (void)displayLayer:(CALayer *)layer的情况下,底层实现在设置.image属性的时候,没有设置layer.contents,就由可能出现改问题。而iOS14以下版本,可能实现逻辑不一样,底层会设置layer.contents。

作者:双鱼子曰1987
链接:https://www.jianshu.com/p/9c117dbe22a8
来源:简书

Activity

afskalsfk

afskalsfk commented on Sep 17, 2020

@afskalsfk
Author

修改成上述这样解决,如有更好办法,麻烦作者更新下

oshiwei

oshiwei commented on Sep 27, 2020

@oshiwei

有人继续维护这个库吗?

TungKamLau

TungKamLau commented on Sep 27, 2020

@TungKamLau

暂时可以采用 @afskalsfk 的方法解决

yuanjunxiao

yuanjunxiao commented on Sep 27, 2020

@yuanjunxiao

目前只能这样解决了,创建一个YYAnimatedImageView的分类,通过方法交换。

  • (void)load {
    // 获取系统的方法
    Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
    // 获取更新的方法
    Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
    // 方法交换
    method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
    }
  • (void)displayLayerNew:(CALayer *)layer {
    Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame");
    UIImage *image = object_getIvar(self, imageIvar);
    if (image)
    {
    layer.contents = (__bridge id)image.CGImage;
    }
    else
    {
    if (@available(iOS 14.0, *))
    {
    [super displayLayer:layer];
    }
    }
    }
TungKamLau

TungKamLau commented on Sep 27, 2020

@TungKamLau

@yuanjunxiao 可以,采用了

oshiwei

oshiwei commented on Sep 29, 2020

@oshiwei

目前只能这样解决了,创建一个YYAnimatedImageView的分类,通过方法交换。

  • (void)load {
    // 获取系统的方法
    Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
    // 获取更新的方法
    Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
    // 方法交换
    method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
    }

  • (void)displayLayerNew:(CALayer *)layer {
    Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame");
    UIImage *image = object_getIvar(self, imageIvar);
    if (image)
    {
    layer.contents = (__bridge id)image.CGImage;
    }
    else
    {
    if (@available(iOS 14.0, *))
    {
    [super displayLayer:layer];
    }
    }
    }

分类直接就可以覆盖原来方法了,不用swizzling

CoderLawrence

CoderLawrence commented on Dec 2, 2020

@CoderLawrence

目前只能这样解决了,创建一个YYAnimatedImageView的分类,通过方法交换。

  • (void)load {
    // 获取系统的方法
    Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
    // 获取更新的方法
    Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
    // 方法交换
    method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
    }
  • (void)displayLayerNew:(CALayer *)layer {
    Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame");
    UIImage *image = object_getIvar(self, imageIvar);
    if (image)
    {
    layer.contents = (__bridge id)image.CGImage;
    }
    else
    {
    if (@available(iOS 14.0, *))
    {
    [super displayLayer:layer];
    }
    }
    }

分类直接就可以覆盖原来方法了,不用swizzling

可以保证执行的顺序吗,应该要调整分类的编译顺序对吧

oshiwei

oshiwei commented on Dec 2, 2020

@oshiwei

目前只能这样解决了,创建一个YYAnimatedImageView的分类,通过方法交换。

  • (void)load {
    // 获取系统的方法
    Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
    // 获取更新的方法
    Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
    // 方法交换
    method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
    }
  • (void)displayLayerNew:(CALayer *)layer {
    Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame");
    UIImage *image = object_getIvar(self, imageIvar);
    if (image)
    {
    layer.contents = (__bridge id)image.CGImage;
    }
    else
    {
    if (@available(iOS 14.0, *))
    {
    [super displayLayer:layer];
    }
    }
    }

分类直接就可以覆盖原来方法了,不用swizzling

可以保证执行的顺序吗,应该要调整分类的编译顺序对吧

分类的方法都是放在类原来方法的前面,没有编译顺序的问题。除非你有多个分类,重写了相同的方法,才会存在分类的编译顺序问题。

CoderLawrence

CoderLawrence commented on Dec 2, 2020

@CoderLawrence

目前只能这样解决了,创建一个YYAnimatedImageView的分类,通过方法交换。

  • (void)load {
    // 获取系统的方法
    Method displayLayerMethod = class_getInstanceMethod(self, @selector(displayLayer:));
    // 获取更新的方法
    Method displayLayerNewMethod = class_getInstanceMethod(self, @selector(displayLayerNew:));
    // 方法交换
    method_exchangeImplementations(displayLayerMethod, displayLayerNewMethod);
    }
  • (void)displayLayerNew:(CALayer *)layer {
    Ivar imageIvar = class_getInstanceVariable([self class], "_curFrame");
    UIImage *image = object_getIvar(self, imageIvar);
    if (image)
    {
    layer.contents = (__bridge id)image.CGImage;
    }
    else
    {
    if (@available(iOS 14.0, *))
    {
    [super displayLayer:layer];
    }
    }
    }

分类直接就可以覆盖原来方法了,不用swizzling

可以保证执行的顺序吗,应该要调整分类的编译顺序对吧

分类的方法都是放在类原来方法的前面,没有编译顺序的问题。除非你有多个分类,重写了相同的方法,才会存在分类的编译顺序问题。

是的,除非有多个分类重写了这个方法

yangfangxue

yangfangxue commented on Apr 17, 2024

@yangfangxue

1

yangfangxue

yangfangxue commented on Apr 17, 2024

@yangfangxue

MARK

tom2025888

tom2025888 commented on Apr 17, 2024

@tom2025888
Svyanto

Svyanto commented on Apr 17, 2024

@Svyanto
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @oshiwei@yuanjunxiao@tom2025888@yangfangxue@CoderLawrence

        Issue actions

          ios14YYAnimatedImageView图片显示问题 · Issue #573 · ibireme/YYKit