完美解决LaunchScreen.storyboard启动图更新失效问题

背景

在不久前接到了换壳工程的项目后,为了能够快速部署新的APP,启动图由原来的LaunchImage(Assets)改为LaunchScreen.storyboard故事版方案,只需提供一张图即可快速更新启动图,后者也是苹果官方最为推荐的方式。然而,刚刚接收到新的需求是更新启动图,换图之后不生效,最后重启手机重装APP才生效,但是这种极差的用户体验就别拿出来说事了。

原因

通过谷歌得知,苹果系统对LaunchScreen.storyboard设置的启动图有缓存,因此不能及时更新,至于多久能更新,不知道,也等不起。

谷歌方案

通过谷歌,各路大神各显神通,有说重启Xcode的、清理Xcode缓存的、卸载APP的、重启手机的、有说图片改名字的、有说改为LaunchImage模式的、也有说删除系统缓存的启动图的,甚至贴出了代码:

NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/SplashBoard/Snapshots"];
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];

甚至更加复杂的代码:

float systemVersion = [[UIDevice currentDevice].systemVersion floatValue];
if (systemVersion >= 13.0 && systemVersion < 14.0) {
    NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSString *folderPath = [documentsPath stringByAppendingPathComponent:@"Data"];
    NSString *imageCachePath = [folderPath stringByAppendingPathComponent:@"SplashBoard"]; // ~/Documents/Data/SplashBoard
    // 准备
    BOOL isDirectory = YES;
    if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:&isDirectory]) {
        [[NSFileManager defaultManager]  createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    NSError *error = nil;
    // 1.获取Images.xcassets中启动图
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
    NSAssert(sb != nil, @"未找到 LaunchScreen.storyboard 文件");
    UIViewController *vc = [sb instantiateInitialViewController];
    UIImage *currentImage = nil;
    for (UIView *subview in vc.view.subviews) {
        if ([subview isKindOfClass:[UIImageView class]]) {
            currentImage = ((UIImageView *)subview).image;
            break;
        }
    }
    if (currentImage == nil) {
        NSAssert(currentImage != nil, @"LaunchScreen.storyboard 中缺少 ImageView");
        return;
    }
    NSData *currentData = UIImagePNGRepresentation(currentImage);
    // 2.获取缓存的启动图
    NSData *cachedData = [[NSData alloc] initWithContentsOfFile:imageCachePath];
    if (cachedData && [cachedData isEqualToData:currentData]) {
        return;
    }
    [[NSFileManager defaultManager] removeItemAtPath:[NSHomeDirectory() stringByAppendingString:@"/Library/SplashBoard"] error:nil];
    [currentData writeToFile:imageCachePath atomically:YES];
}

我想说的是,各位大神,您试了,各种场景下,真的都没问题吗?
建议,自测真正有效并且稳定的方案再贴出来,防止更多人迷路。但是,还是要感谢这么多的技术大神,勇于分享自己的实践和理解,值得我们大家学习。

完美方案

废话话不多说,100%成功且稳定的方案:

  1. 新建不同名称的启动页.storyboard,作为启动页,并删除旧的。
  2. 新的启动图片需要重新命名,并且需要放在工程文件夹下(无需根目录),不能放在Assets里面。
这二者缺一不可 !!!

简单步骤

防止部分小伙伴理解偏差,我贴下步骤图:

  1. 假如原来的启动图为:Launch Screen.storyboard


    image.png
  2. 可以新建个故事版叫:NBLaunchScreen.storyboard,然后重新添加ImageView设置约束,添加启动图片,重新设置为启动图。


    image.png
  3. 假设原来的图片名称为launch.png,新的启动图命名为start0.png,并设置为启动图


    image.png

完美,收工,适用于任何场景,启动图立即更新,不掺杂任何杂质。

重要补充

在执行前面的步骤后,若再有新的启动图更换需求,使用上次的启动页.storyboard即可,比如上次已经改为:NBLaunchScreen.storyboard,本次就无须改名了,只需更改图片名称并重新添加到NBLaunchScreen.storyboard就行,同时支持不同旧版本升级替换,也就是说,苹果只会对默认的Launch Screen.storyboard进行故事版的缓存。

知识点+小妙招

  1. 苹果对启动图的缓存应该同时使用了storyboard+图片作为索引。
  2. storyboard比LaunchImage(Assets)优先级高,前者方案可以更改为后者,但是后者不可更改为前者。
  3. storyboard上的图片建议设置Aspect Fit自适应,图片建议用一张1242 × 2688尺寸的(高度最高的),设计图案尽量靠中间并且整个图片透明,storyboard的view层设置背景颜色,这样不同机型包括iPad都能适配。
  4. 预祝正在阅读的你春节快乐。

你可能感兴趣的:(完美解决LaunchScreen.storyboard启动图更新失效问题)