紧急需求‼️实现iOS启动图动态置灰

前言

相信这几天各大互联网应用首页置灰已经接踵而至,事情缘由我就不太赘述。毫无疑问,我司从30号当晚就收到紧急需求,我们要求1号必须紧急发版,除了常规的首页支持配置的动态置灰外,我们还要求另外一个需求就是,启动图也需要支持动态配置灰功能,经过几个同事的努力,于1号当晚顺利的发版了,第二天一早便成功上线,在此记录一下实现iOS启动图动态置灰的方案心得。

方案过程

实话说,当我接到此需求时,我负责的是实现iOS启动图动态置灰,当时我不太确认是否能实现,我能想到的是马上搜百度、谷歌、掘金等看是否有现成的轮子,答案肯定是有的,分别是

此方案非常轻量级,只有BBADynamicLaunchImage一个类,功能也只有一个,即查找系统缓存的启动图路径,使用我们提供的UIImage替换掉。其他版本控制本非必要需求我们自己代码控制即可。最终我也是直接采用了这个方案,其他控制由我代码自己编写核心方法如下。PS:(虽然提供iOS13之前的启动图路径查找,但是经过我实测一台iOS12的设备是不生效的,只有iOS13意思机型生效)


/// 系统启动图缓存路径
+ (NSString *)launchImageCacheDirectory {

    NSString *bundleID = [NSBundle mainBundle].infoDictionary[@"CFBundleIdentifier"];
    NSFileManager *fm = [NSFileManager defaultManager];

    // iOS13之前
    NSString *cachesDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSString *snapshotsPath = [[cachesDirectory stringByAppendingPathComponent:@"Snapshots"] stringByAppendingPathComponent:bundleID];
    if ([fm fileExistsAtPath:snapshotsPath]) {
        return snapshotsPath;
    }
    
    // iOS13
    NSString *libraryDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
    snapshotsPath = [NSString stringWithFormat:@"%@/SplashBoard/Snapshots/%@ - {DEFAULT GROUP}", libraryDirectory, bundleID];
    if ([fm fileExistsAtPath:snapshotsPath]) {
        return snapshotsPath;
    }
    
    return nil;
}

稍微吐槽下这个库,此库也是我一开始使用的。它也是基于BBADynamicLaunchImage做了一些拓展。比如版本控制,但是它内置的版本控制有漏洞,它只支持CFBundleShortVersionString,也就是我们俗称的大版本,如果我build号改了版本号不变岂不是有问题?(这也是我打包后不生效调试了好久才发现的问题)而且要支持动态置灰,不发版恢复原图就更加有问题。最后也是弃用了,当然这个库支持暗黑模式下的启动图,但是我本身app就是不支持的这个功能就聊胜于无了,最终该用了上边的方案,动态控制由我自己处理。

启动图如何置灰

要实现启动图和原图一模一样只是变成灰白,这里就稍微要花一点点心思了。众所周知我们现在iOS启动图都是直接用LaunchScreen这个Storyborad生成的,那我们是否能加载这个LaunchScreen,然后截取UIView的图片,之后再通过bitmap转换成一张灰白图?答案是显而易见的,代码如下。

首先我们要给LaunchScreen定义一个id,因为默认没有人去加载它,它也没有id。

代码如下:


+ (UIImage *)createLaunchScreenImage:(BOOL)isNeedGray {
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
    UIViewController *vc = [sb instantiateViewControllerWithIdentifier:@"LaunchScreen"];
    [vc loadViewIfNeeded];
    vc.view.frame = UIScreen.mainScreen.bounds;
    UIImage *image = [vc.view snapshotImage];
    if (isNeedGray) {
        image = [image createGrayImage];
    }
    return image;
}


UIView截图


func snapshotImage() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0);
        self.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }



生成灰白图方法,由于启动图必须size匹配,所以scale那些要处理好。


-(UIImage*)createGrayImage {
    int width = self.size.width * self.scale;
    int height = self.size.height * self.scale;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef context =CGBitmapContextCreate(nil,
                                               width,
                                               height,
                                               8,// bits per component
                                               0,
                                               colorSpace,
                                               kCGBitmapByteOrderDefault);
    CGColorSpaceRelease(colorSpace);
    if(context ==NULL) {
        return nil;
    }
    CGContextDrawImage(context,
                       CGRectMake(0,0, width, height), self.CGImage);
    UIImage*grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context) scale:self.scale orientation:self.imageOrientation];
    CGContextRelease(context);
    return grayImage;
}

动态替换

我们只需要请求后台配置,需要灰白就提供灰白图,当配置失效,需要还原时候,根据上面方法,直接渲染一个LaunchScreen原图即可,当然其中还要做好持久化控制,不要处理多次替换,替换生效后不再处理。

末尾

以上就是我实现此次iOS启动图动态置灰的全过程,由于过程的艰辛,加之我自己是一个Swifter。估计不久将来,我也会基于Swift写一个稍微友好点的库,在此立个Flag。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值