16

I am able to display the build date for my app in the simulator, but whenever I archive the app, and upload it to TestFlight, and then install it on a device, the build date doesn't show.

Here is what I'm doing to display the build date.

First, I added CFBuildDate as a string to myproject-info.plist

Next, I added the following script to 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

Finally, used the following code to get the build date from the plist file :

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

This displays the build date in simulator (though occasionally it doesn't), but when deploying the app through TestFlight, the build date never displays. Any ideas ?

Thanks in advance.

Myxtic
  • 5,679
  • 5
  • 48
  • 69
  • 1
    Try running the script as a *build step* so it's run all the time, regardless of the type of build you are producing. – trojanfoe Aug 02 '12 at 14:30
  • Why do you need the build date? – AppHandwerker Aug 02 '12 at 14:35
  • @trojanfoe - So I added the same script as a new Run Script in Build Phases. Will try that get back to you with the results. – Myxtic Aug 02 '12 at 14:44
  • @SimonH - I know it's not that important, but some of the testers in my company have requested that to keep track of the builds. – Myxtic Aug 02 '12 at 14:45
  • Surely updating the build/version number would be better +I know this works :) – AppHandwerker Aug 02 '12 at 14:48
  • Agreed. See this excellent SO question of mine :D http://stackoverflow.com/questions/9258344/xcode-better-way-of-incrementing-build-number – trojanfoe Aug 02 '12 at 15:12
  • @trojanfoe Running script in build phases worked ! Thanks so much. If you can post your solution as the answer, I'd be happy to accept it. – Myxtic Aug 02 '12 at 19:21
  • I don't know how to use Objective-C to handle this. However, I successfully did this with Swift. You can manually expose my Swift solution to Objective-C by adding an @objc prefix towards my method: https://stackoverflow.com/a/76731173/4162914 Note that the essense is to verify the codesign timestamp, hence the requirements that your app must be propertly signed by Apple using your Developer ID Application certificate. – Shiki Suen Jul 20 '23 at 16:15

7 Answers7

28

You might consider using the built-in __DATE__ and __TIME__ macros which will return a string representation of the date and time the app was built. Perhaps they will be of more help to you:

NSString *dateStr = [NSString stringWithUTF8String:__DATE__];
NSString *timeStr = [NSString stringWithUTF8String:__TIME__];
Jeremy
  • 8,902
  • 2
  • 36
  • 44
  • +1 Haven't tried that, but looks like an elegant solution. Thanks ! – Myxtic Aug 02 '12 at 20:08
  • That's a good solution, however the date/time aren't within the `Info.plist` file, and therefore are not externally visible. – trojanfoe Aug 03 '12 at 07:58
  • What is 'externally visible'? It will be accessible to the build_date variable. – Jeremy Aug 03 '12 at 13:18
  • Keep in mind that the `__DATE__` and `__TIME__` constants are in the developer machine's local time. There's no constant that tells you what that is. – Michael Melanson Nov 18 '14 at 22:04
  • 2
    in order for this to be build date and time for whole project I added a pre build script line to touch file with this code otherwise the timestamp is when that file was last modified, not timestamp of build – godzilla Apr 01 '16 at 20:29
  • This does not work well - the date will *only* be updated when the source file with this code needs to be recompiled. So, if you forget to clean your project before building and also have not made any changes to this file, you will end up getting the last modification date of that file, not of your latest build process. – Thomas Tempelmann Nov 08 '19 at 13:13
12

To get build date with format 'yyMMddHHmm' you could try this:

+ (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;
}
Muhammad Nabeel Arif
  • 19,140
  • 8
  • 51
  • 70
Dirk Schmidt
  • 121
  • 1
  • 3
  • 2
    Nice :) but dont forget to set the locale, or it will not work everywhere. [dateFormatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US"]]; – roberto.buratti Jul 10 '14 at 16:56
  • This does not work well - the date will *only* be updated when the source file with this code needs to be recompiled. So, if you forget to clean your project before building and also have not made any changes to this file, you will end up getting the last modification date of that file, not of your latest build process. – Thomas Tempelmann Nov 08 '19 at 13:13
8

Try running the script as a build phase step, rather than a scheme pre-action step, so it's run all the time, regardless of the type of build you are producing.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
6

If you redefine __DATE__ and __TIME__ it will make the time update every time you build your app. you won´t need to clean or archive to update the time, just need run the project.

  #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;
}
mylogon
  • 2,772
  • 2
  • 28
  • 42
Pedro
  • 487
  • 1
  • 5
  • 18
  • This does not work well - the date will *only* be updated when the source file with this code needs to be recompiled. So, if you forget to clean your project before building and also have not made any changes to this file, you will end up getting the last modification date of that file, not of your latest build process. – Thomas Tempelmann Nov 08 '19 at 13:13
6

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)
}
Community
  • 1
  • 1
neoneye
  • 50,398
  • 25
  • 166
  • 151
  • 1
    This is not giving a consistent result with `__DATE__` since when you update your app info.plist will remain the same while `__DATE__` gets proper updated by the time of the update. – Viktor Kucera Mar 21 '17 at 16:02
0

On macOS, I use this code, which fetches the build date from the app's Info.plist content. Might also work on iOS, I haven't checked:

+ (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;
}
Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
-4

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)
Arunabh Das
  • 13,212
  • 21
  • 86
  • 109