Skip to content

Instantly share code, notes, and snippets.

@steipete
Last active October 30, 2019 03:49
Show Gist options
  • Save steipete/7668246 to your computer and use it in GitHub Desktop.
Save steipete/7668246 to your computer and use it in GitHub Desktop.
Detect if you're currently running a development version or an App Store/Ad Hoc version.
static BOOL PSPDFIsDevelopmentBuild(void) {
#if TARGET_IPHONE_SIMULATOR
return YES;
#else
static BOOL isDevelopment = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// There is no provisioning profile in AppStore Apps.
NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]];
if (data) {
const char *bytes = [data bytes];
NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length];
for (NSUInteger i = 0; i < data.length; i++) {
[profile appendFormat:@"%c", bytes[i]];
}
// Look for debug value, if detected we're a development build.
NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:@""];
isDevelopment = [cleared rangeOfString:@"<key>get-task-allow</key><true/>"].length > 0;
}
});
return isDevelopment;
#endif
}
@steipete
Copy link
Author

This is all based on public API and App Store safe. Used in http://PSPDFKit.com

@rbsgn
Copy link

rbsgn commented Nov 27, 2013

Actually "embedded.mobileprovision" is not a public API. it is an implementation detail that might change in future

@prrane
Copy link

prrane commented Nov 27, 2013

We set a Preprocessor Macro, but this looks more hip :-0

@dhoepfl
Copy link

dhoepfl commented Nov 27, 2013

Why do you use NSData and a manual to-string-conversion instead of

NSString *profile = [NSString stringWithContentsOfFile:...
                                              encoding:NSISOLatin1StringEncoding
                                                 error:&err];

(NSISOLatin1StringEncoding as a "accept any byte value, 0..127 is ASCII")

@steipete
Copy link
Author

@nskboy It defaults to NO, so if this changes nothing will go wrong, we just falsely detect an AppStore/AdHoc build. This is only used to be developer-friendly and provide more logs/alerts when using certain features during development.

@steipete
Copy link
Author

@dhoepfl I tried that. This will pick up \0 's from the binary part and prematurely end the string.

@rbsgn
Copy link

rbsgn commented Nov 27, 2013

I mean existence of a file embedded.mobileprovision rather than get-task-allow itself

@Duraiamuthan
Copy link

@steipete Good thinking

@jarnoh
Copy link

jarnoh commented Nov 4, 2014

I tried this snippet in a production app a while back, this snippet caused a crash on ~0.1% of users.

@ghazel
Copy link

ghazel commented Feb 10, 2015

What was the crash?

@loretoparisi
Copy link

To avoid crashes I suggest to check only

+ (BOOL)isDevelopmentBuild {
#if TARGET_IPHONE_SIMULATOR
    return YES;
#else
    static BOOL isDevelopment = NO;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // There is no provisioning profile in AppStore Apps.
        NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"]];
        if (data) {
            isDevelopment=YES;
        }
    });
    return isDevelopment;
#endif
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment