【问题标题】:Showing App's Build Date显示应用的构建日期
【发布时间】:2012-07-31 12:56:03
【问题描述】:

我能够在模拟器中显示我的应用程序的构建日期,但是每当我将应用程序存档并将其上传到 TestFlight,然后将其安装到设备上时,构建日期都不会显示。

这是我为显示构建日期所做的工作。

首先,我将 CFBuildDate 作为字符串添加到 myproject-info.plist

接下来,我在 Edit Scheme -> Build -> Pre-Actions -> Run Script Action 中添加了以下脚本:

infoplist="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
builddate=`date`
if [[ -n "$builddate" ]]; then
/usr/libexec/PlistBuddy -c "Add :CFBuildDate $builddate" ${infoplist}
/usr/libexec/PlistBuddy -c "Set :CFBuildDate $builddate" ${infoplist}
fi

最后,使用以下代码从 plist 文件中获取构建日期:

NSString *build_date = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBuildDate"];

这会在模拟器中显示构建日期(虽然偶尔不会),但是当通过 TestFlight 部署应用程序时,构建日期永远不会显示。有什么想法吗?

提前致谢。

【问题讨论】:

  • 尝试将脚本作为 构建步骤 运行,这样它就会一直运行,而不管您生成的构建类型如何。
  • 为什么需要构建日期?
  • @trojanfoe - 所以我在构建阶段添加了与新运行脚本相同的脚本。将尝试将结果回复您。
  • @SimonH - 我知道这并不重要,但我公司的一些测试人员要求跟踪构建。
  • 当然更新构建/版本号会更好+我知道这可行:)

标签: objective-c ios xcode build


【解决方案1】:

您可以考虑使用内置的 __DATE____TIME__ 宏,它们将返回应用程序构建日期和时间的字符串表示形式。也许他们会对你有更多帮助:

NSString *dateStr = [NSString stringWithUTF8String:__DATE__];
NSString *timeStr = [NSString stringWithUTF8String:__TIME__];

【讨论】:

  • +1 没试过,但看起来是一个优雅的解决方案。谢谢!
  • 这是一个很好的解决方案,但是日期/时间不在Info.plist 文件中,因此在外部不可见。
  • 什么是“外部可见”? build_date 变量可以访问它。
  • 请记住,__DATE____TIME__ 常量是开发人员机器的本地时间。没有常数可以告诉你那是什么。
  • 为了将其作为整个项目的构建日期和时间,我添加了一个预构建脚本行来使用此代码触摸文件,否则时间戳是该文件最后一次修改的时间,而不是构建的时间戳
【解决方案2】:

要获取格式为“yyMMddHHmm”的构建日期,您可以尝试以下操作:

+ (NSString *)GetBuildDate {
    NSString *buildDate;

    // Get build date and time, format to 'yyMMddHHmm'
    NSString *dateStr = [NSString stringWithFormat:@"%@ %@", [NSString stringWithUTF8String:__DATE__], [NSString stringWithUTF8String:__TIME__]];

    // Convert to date
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"LLL d yyyy HH:mm:ss"];
    NSDate *date = [dateFormat dateFromString:dateStr];

    // Set output format and convert to string
    [dateFormat setDateFormat:@"yyMMddHHmm"];
    buildDate = [dateFormat stringFromDate:date];

    [dateFormat release];

    return buildDate;
}

【讨论】:

  • 不错 :) 但不要忘记设置语言环境,否则它不会在任何地方都有效。 [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US"]];
  • 这不好用 - 日期将在需要重新编译包含此代码的源文件时更新。因此,如果您忘记在构建之前清理您的项目并且也没有对此文件进行任何更改,您最终将获得该文件的最后修改日期,而不是您最新的构建过程。
【解决方案3】:

尝试将脚本作为构建阶段步骤运行,而不是方案预操作步骤,这样它就会一直运行,而不管您正在生成的构建类型如何。

【讨论】:

    【解决方案4】:

    Swift3

    static var buildDate: Date? {
        guard let infoPath = Bundle.main.path(forResource: "Info.plist", ofType: nil) else {
            return nil
        }
        guard let infoAttr = try? FileManager.default.attributesOfItem(atPath: infoPath) else {
            return nil
        }
        let key = FileAttributeKey(rawValue: "NSFileCreationDate")
        guard let infoDate = infoAttr[key] as? Date else {
            return nil
        }
        return infoDate
    }
    
    static var prettyBuildDate: String {
        guard let date = buildDate else {
            return "Unknown"
        }
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        formatter.timeZone = TimeZone(abbreviation: "UTC")
        return formatter.string(from: date)
    }
    

    【讨论】:

    • 这与__DATE__ 给出的结果不一致,因为当您更新应用程序时,info.plist 将保持不变,而__DATE__ 在更新时得到正确更新。
    【解决方案5】:

    如果您重新定义__DATE____TIME__,它将在您每次构建应用程序时更新时间。您无需清理或存档即可更新时间,只需运行项目即可。

      #define DATE [NSString stringWithUTF8String:__DATE__]
      #define TIME [NSString stringWithUTF8String:__TIME__]
    
    
    - (NSString *)getBuildDate {
        NSString *buildDate;
    
        // Get build date and time, format to 'yyMMddHHmm'
        NSString *dateStr = [NSString stringWithFormat:@"%@ %@", DATE , TIME ];
    
        // Convert to date
        NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
        [dateFormat setDateFormat:@"LLL d yyyy HH:mm:ss"];
        NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
        [dateFormat setLocale:usLocale];
        NSDate *date = [dateFormat dateFromString:dateStr];
    
        // Set output format and convert to string
        [dateFormat setDateFormat:@"dd/MM/yyyy-HH:mm"];
        buildDate = [dateFormat stringFromDate:date];
    
        return buildDate;
    }
    

    【讨论】:

    • 这不好用 - 日期将在需要重新编译包含此代码的源文件时更新。因此,如果您忘记在构建之前清理您的项目并且也没有对此文件进行任何更改,您最终将获得该文件的最后修改日期,而不是您最新的构建过程。
    【解决方案6】:

    在 macOS 上,我使用此代码,它从应用程序的 Info.plist 内容中获取构建日期。可能也适用于 iOS,我还没有检查:

    + (NSDate *)buildDate {
        static NSDate *result = nil;
        if (result == nil) { 
            NSDictionary *infoDictionary = NSBundle.mainBundle.infoDictionary;
            NSString *s = [infoDictionary valueForKey:@"BuildDateString"];
            NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
            NSDate *d = [formatter dateFromString:s];
            result = d;
        }
        return result;
    }
    

    【讨论】:

      【解决方案7】:

      Swift5

      let compileDate = String(Date())
      let df = DateFormatter()
      df.dateFormat = "MMM-dd-yyyy"
      let usLocale = NSLocale(localeIdentifier: "en_US")
      df.locale = usLocale
      let aDate: Date? = df.date(from: compileDate)
      

      【讨论】:

      • Date() 返回运行时间,而不是编译时间
      猜你喜欢
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多