You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS/Swift/SwiftUI如何仅对旧版升级老用户执行指定代码

实现方案

核心判断逻辑基于本地非同步持久化标记+版本追踪,同时兼容已上线无预埋标记的1.0存量版本,不会误判重装用户、跨设备同步用户。

避坑前置说明

以下方案误判率极高,不建议使用:

  • 不要用Keychain存储判断标记:用户删除App重装时,Keychain数据可能不会被系统清空,会将重装用户误判为升级老用户
  • 不要用开启iCloud同步的存储区存标记:同Apple ID下的多设备会同步标记,导致新设备全新安装被误判
  • 不要只依赖首次启动判断:不做版本号匹配的话,后续大版本升级会重复触发逻辑

具体实现步骤

  • 第一步:选定存储位置
    用系统默认的UserDefaults(本地域,不要手动开启iCloud同步)或者沙盒Application Support目录下的本地配置文件存标记即可,这类数据的特性是:App删除后会被系统完全清空,不会残留,刚好匹配判断需求。
  • 第二步:兼容无预埋的1.0版本
    因为已经上线的1.0版本没有提前写入任何版本标记,需要做一层兜底判断:
    • 如果你1.0版本运行时会在本地写入固定业务数据(比如登录态、本地缓存、自定义配置文件),直接检查这类数据是否存在即可,存在就是1.0升级的老用户
    • 如果1.0版本没有写入任何业务数据,就用沙盒目录创建时间差判断:升级安装时系统会替换App的bundle文件,但会保留原沙盒的Documents/Library目录,这两个目录的创建时间是用户最初安装1.0的时间,远早于2.0版本bundle的创建时间;全新安装时沙盒目录和bundle是安装过程中连续创建的,时间差在10秒以内,设置60秒的阈值就能100%区分两类用户。
  • 第三步:版本标记与执行防重
    判断完成后立刻做两个持久化写入:
    1. 写入当前App的版本号作为kAppLastLaunchedVersion,供后续版本升级判断使用
    2. 如果判定为1.0升级用户,额外写入kHasRunV2SpecialLogic的布尔标记,确保这段特殊逻辑在用户整个App生命周期里只执行一次,不会因为后续版本升级、重复启动重复触发。

代码示例

// 建议在application:didFinishLaunchingWithOptions:最靠前的位置调用,不要放在异步队列
- (BOOL)shouldRunV2ExclusiveLogic {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    // 已经执行过特殊逻辑,直接返回NO
    if ([defaults boolForKey:@"kHasRunV2SpecialLogic"]) {
        return NO;
    }
    
    NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString *lastLaunchedVersion = [defaults stringForKey:@"kAppLastLaunchedVersion"];
    
    // 之前已经写入过版本标记,直接对比版本
    if (lastLaunchedVersion) {
        // 判断之前的版本是否低于2.0
        BOOL isUpgradeFromV1 = [lastLaunchedVersion compare:@"2.0" options:NSNumericSearch] == NSOrderedAscending;
        [defaults setObject:currentVersion forKey:@"kAppLastLaunchedVersion"];
        if (isUpgradeFromV1) {
            [defaults setBool:YES forKey:@"kHasRunV2SpecialLogic"];
        }
        [defaults synchronize];
        return isUpgradeFromV1;
    }
    
    // 没有历史版本标记,走兜底判断(针对1.0版本无预埋的场景)
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // 获取当前App bundle的创建时间,即本次安装/升级到2.0的时间
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
    NSDate *bundleCreateDate = [[fileManager attributesOfItemAtPath:bundlePath error:nil] fileCreationDate];
    // 获取Documents目录创建时间
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSDate *docCreateDate = [[fileManager attributesOfItemAtPath:docPath error:nil] fileCreationDate];
    
    // 时间差大于60秒说明Documents目录远早于2.0安装时间创建,是1.0升级用户
    NSTimeInterval timeGap = [bundleCreateDate timeIntervalSinceDate:docCreateDate];
    BOOL isV1User = timeGap > 60;
    
    // 写入标记
    [defaults setObject:currentVersion forKey:@"kAppLastLaunchedVersion"];
    if (isV1User) {
        [defaults setBool:YES forKey:@"kHasRunV2SpecialLogic"];
    }
    [defaults synchronize];
    
    return isV1User;
}

调用时直接匹配原有逻辑即可:

if ([self shouldRunV2ExclusiveLogic]) {
    // 执行仅针对1.0升级用户的特殊代码
}

内容的提问来源于stack exchange,提问作者fs_tigre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 10:21:39