xcode12环境下iOS14兼容问题汇总

1、UIProgressView高度问题

在xcode12环境下的iOS14系统,UIProgressView的默认高度有8像素左右,需要做相应的适配

/* Xcode12-IOS14的兼容 */
if (@available(iOS 14.0, *)) {
    CGAffineTransform transform = CGAffineTransformMakeScale(1.0f, 1.0f);
    transform = CGAffineTransformMakeScale(1.0f, 0.5f);
    _progressView.transform = transform;
}

2、iOS14.0-14.1导航栏堆栈推出导致Tabbar隐藏

iOS14.0与IOS14.1导航栏堆栈推出后,Tabbar会被隐藏,iOS14.2没有发现该问题

- (NSArray<UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated {
    if (@available(iOS 14.0, *)) {
        if (self.viewControllers.count > 1) {
            self.topViewController.hidesBottomBarWhenPushed = NO;
        }
    };
    return [super popToRootViewControllerAnimated:animated];
}

- (NSArray<UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (@available(iOS 14.0, *)) {
        if (self.viewControllers.count > 1) {
            self.topViewController.hidesBottomBarWhenPushed = NO;
        }
    };
    return [super popToViewController:viewController animated:animated];
}

3、UITabViewCell添加subView的方式

iOS14推荐使用[UITabViewCell.contentView addSubview:],不推荐使用[UITabViewCell addSubview:] 

4、获取IDFA的差异

在xcode12环境下的iOS14系统,获取到IDFA信息需要配置NSUserTrackingUsageDescription,且用户授权。

配置如下:

<!-- info.plist -->
<key>NSUserTrackingUsageDescription</key>
<string>需要使用您的广告追踪权限来追踪广告</string>
/* xcode12&iOS14兼容 */
if (@available(iOS 14.0, *)) {
    [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
            NSString * strAdid = [[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    }];
 }

5、WXImageView、FLAnimatedImage、YYAnimatedImage图片加载不出来

在iOS 14之前,UIKit在调用displayLayer:之前就会去渲染UIImageView.image;而在iOS 14,UIKit则是先去调用displayLayer:,如果你实现了displayLayer:,那么UIKit就不会再去渲染了。

@implementation WXImageView
...

- (void)setImage:(UIImage *)image {
    [super setImage:image];
    if (image) {
        self.layer.contents = (id)image.CGImage;
    } else {
        self.layer.contents = nil;
    }
}

@end
@implementation FLAnimatedImageView
...

- (void)displayLayer:(CALayer *)layer {
    if (_currentFrame) {
        layer.contentsScale = _currentFrame.scale;
        layer.contents = (__bridge id)_currentFrame.CGImage;
    } else {
        // If we have no animation frames, call super implementation. iOS 14+ UIImageView use this delegate method for rendering.
        if ([UIImageView instancesRespondToSelector:@selector(displayLayer:)]) {
           [super displayLayer:layer];
        }
    }
}

@end
@implementation YYAnimatedImageView
...

- (void)displayLayer:(CALayer *)layer {
    if (_curFrame) {
        layer.contentsScale = _curFrame.scale;
        layer.contents = (__bridge id)_curFrame.CGImage;
    } else {
        // If we have no animation frames, call super implementation. iOS 14+ UIImageView use this delegate method for rendering.
        if ([UIImageView instancesRespondToSelector:@selector(displayLayer:)]) {
           [super displayLayer:layer];
        }
    }
}

@end

上面的方式是直接到第三库源码修改,也可以通过hook的方式实现,不用去改动第三库的源码。

@implementation WXImageViewHook

+ (void)load {
    /* Xcode12-IOS14的兼容 */
    if (@available(iOS 14.0, *)) {
        [self startHook];
    }
}

+ (void)startHook {
    Class cls =  NSClassFromString(@"WXImageView");

    SEL selector = NSSelectorFromString(@"setImage:");
    
    typedef void (^WXImageViewSetImageBlock)(UIImageView* t_self, UIImage* image);
    
    WXImageViewSetImageBlock implementationBlock = ^(UIImageView* t_self, UIImage* image) {
        struct objc_super t_super = {
            .receiver = t_self,
            .super_class = class_getSuperclass([t_self class])
        };
        void(*msgSendSuper)(struct objc_super*, SEL, UIImage*) = (void*)&objc_msgSendSuper;
        msgSendSuper(&t_super, NSSelectorFromString(@"setImage:"), image);
        
        if (image) {
            t_self.layer.contents = (id)image.CGImage;
        } else {
            t_self.layer.contents = nil;
        }
    };
    
    [MKHookUtil addImplementationOfSelector:selector forClass:cls implementationBlock:implementationBlock];
}

@end
@implementation FLAnimatedImageView (Hook)

+ (void)load {
    /* Xcode12-IOS14的兼容 */
    if (@available(iOS 14.0, *)) {
        [MKHookUtil swizzMethodOriginalSelector:@selector(displayLayer:) swizzledSelector:@selector(swizzing_displayLayer:) forClass:[self class]];
    }
}

- (void)swizzing_displayLayer:(CALayer *)layer {
    Ivar ivar = class_getInstanceVariable(self.class, "_currentFrame");
    UIImage *_currentFrame = object_getIvar(self, ivar);

    if (_currentFrame) {
        layer.contentsScale = _currentFrame.scale;
        layer.contents = (__bridge id)_currentFrame.CGImage;
    } else {
        // If we have no animation frames, call super implementation. iOS 14+ UIImageView use this delegate method for rendering.
        if ([UIImageView instancesRespondToSelector:@selector(displayLayer:)]) {
           [super displayLayer:layer];
        }
    }
}

@end
@implementation YYAnimatedImageView (Hook)

+ (void)load {
    if (@available(iOS 14.0, *)) {
        [MKHookUtil swizzMethodOriginalSelector:@selector(displayLayer:) swizzledSelector:@selector(swizzing_displayLayer:) forClass:[self class]];
    }
}

- (void)swizzing_displayLayer:(CALayer *)layer {
    Ivar ivar = class_getInstanceVariable(self.class, "_curFrame");
    UIImage *_curFrame = object_getIvar(self, ivar);

    if (_curFrame) {
        layer.contentsScale = _curFrame.scale;
        layer.contents = (__bridge id)_curFrame.CGImage;
    } else {
        // If we have no animation frames, call super implementation. iOS 14+ UIImageView use this delegate method for rendering.
        if ([UIImageView instancesRespondToSelector:@selector(displayLayer:)]) {
           [super displayLayer:layer];
        }
    }
}

@end

 

猜你喜欢

转载自blog.csdn.net/z119901214/article/details/110918998