Check If App Is Ad-Hoc|Dev|App-Store Build at Run Time

How to determine at run-time if app is for development, app store or ad hoc distribution?

The easiest way to check is to look at embedded.mobileprovision ([[NSBundle mainBundle] pathForResource:@"embedded.mobileprovision" ofType:nil]):

  • It's a bit of a pain to parse since it's a signed plist (PKCS#7 signed data, according to openssl asn1parse -inform der), but a bad hack is to just look for <plist and </plist>.
  • Development contains UDIDs and <key>get-task-allow</key><true/>
  • Ad Hoc distribution contains UDIDs (and get-task-allow=false)
  • App Store distribution contains no UDIDs.

The other thing you can check is the entitlements embedded in the executable (otool -l lists it as LC_CODE_SIGNATURE). Parsing this is even more tedious (you need to parse the Mach-O header and load commands, and for "universal" binaries which are now the default, you'll need to check the currently-loaded architecture or all architectures).

  • Development builds contain <key>get-task-allow</key><true/>
  • Ad Hoc and App Store builds contain <key>get-task-allow</key><false/>

I don't think the entitlements distinguish between Ad Hoc and App Store builds.

Apart from those and the certificate it's signed with, there's no difference between Development/Ad Hoc/App Store apps (there are a few other things in the entitlements/provisioning profile, but nothing more reliable that I can think of).

Security considerations

Neither of these are that difficult to circumvent. For the first method, the app could just "swizzle" -[NSBundle pathForResource:ofType:]. The second method is a bit more difficult depending on what API you use to read the file.

Check if app is ad-hoc|dev|app-store build at run time

While I would agree with Abhi Beckert that runtime is the wrong time to be doing this (use preprocessor directives and build settings!), I wanted to clarify some of the details and speculations in the previous answer/comments and shine some light on things you could do. Bear with me, this is going to be a longer answer...

There are a bunch of pieces of data that could go under the generic umbrella of 'Build Information'. A non-exhaustive list of such things would include: Build Configuration, Code Signing Identity, Build Time, Build Date, Marketing Version Number, SCM Revision Number, SCM Branch Name, Provisioning Profile Team Identity, Provisioning Profile Expiration, CI Build Number...the list goes on and on.

Assuming for the moment your question was narrowly focused on gaining information as to the type of iOS certificate and Provisioning Profile used for the build, then I will have to go with a very firm 'No' as the answer to the question: Is there a way to check [build information using an existing API method] at runtime? As a brief aside: Collectively these two data points are called the "Code Signing Identity" in Xcode 4.6.x Build Settings or "CODE_SIGN_IDENTITY" for you command-line build setting enthusiasts.

As of the time this question was asked, there is no singular public iOS API that you can call to get information about the code signature type for the currently running app. The likely reasons behind this are numerous, but here are a few examples:

  1. Developers are permitted to construct their own build schemes and build configurations. This means that we can have one scheme and one build configuration, or one scheme and dozens of build configurations, or even thousands of each. Naturally each scheme can be assigned a different build configuration, and those configurations can each be assigned a different code signing identity. As you might guess, it doesn't take much customization by a developer or team for this to quickly get chaotic.
  2. Code signing identities only require that a non-expired Provisioning Profile issued for the current app identifier, contains a copy of the public key for the certificate used to sign the binary. For those working on a team, you might have a single Provisioning Profile containing all the certificates of the developers on the team, or you might make individual Provisioning Profiles for each developer on the team containing only their certificates. This is yet another point of variation in how developers can elect to build their app.
  3. Developers may share a single certificate (tsk tsk) or be issued their own certificates...yep, you guessed it, even more variation.

This hypothetical one-stop API would then need to have access at runtime to all of your build configuration data, certificates, and provisioning profiles to be able to untwist the 'effective' settings applied at compile time and reduce all of that data down to a finite string...simply for a developer diagnostics view...not an impossible feat by any stretch of the imagination, but such a potentially computationally intense operation for negligible developer benefit would definitely rank low on just about anybody's priority list. It would get kicked even further down the priority list given that other options (like compile-time flags!) are more reliable, cheaper to setup, and simpler to maintain in the long run.

Now, as to the semi-lurking question of "Could I do it at runtime?" I would emphatically say 'Yes you can.'

As you know, device builds are the only kinds of builds that require code signing. Part of the process creates a file in the main bundle called 'embedded.mobileprovision'. This is a file owned by your app's sandbox and thus is something you absolutely have the ability to open programmatically:

[[NSBundle mainBundle] pathForResource:@"embedded.mobileprovision" ofType:nil]

.mobileprovision files are PCKS#7 encoded and contain both binary and text data. The info you seek is that of the text-based plist embedded within the PCKS#7 data. First, using OS X let's take a look at this text data out of one of your device builds:

  1. Right click on your build for device .app bundle and select 'Show Package Contents'
  2. Copy the embedded.mobileprovision file someplace easily accessible.
  3. Open that file with your preferred text editor.

You notice right away that there's a lot of binary data but you can make out parts of the text data. Scrolling to the right, you'll see plist-styled xml, only it isn't so easy to read in this view. We can use an OS X command line tool to look at this data in a more organized manner:

  1. Open Terminal and 'cd' to the folder containing your copy of the embedded.mobileprovision.
  2. Run: security cms -D -i embedded.mobileprovision

This will display the plist xml to the terminal window for your perusal in a nicely tabbed format. If you repeat this process for an Ad-Hoc build, Dev build, and an App Store build you'll start to notice the keys in this text that are indicative of the respective types of builds. For builds signed with an 'iPhone Developer: ...' certificate (or 'Dev' builds as you listed in the original post), look for:

<key>get-task-allow</key>
<true/>

The 'get-task-allow' key is what is used to instruct iOS if the app will allow a debugger to attach to it. In the case of an 'iPhone Developer' signed binary this makes sense - You would typically need to be able to debug on the device when pushing code from Xcode to your device for testing purposes.

The difference between 'Ad-Hoc' and 'App Store' require some additional checks. This same 'get-task-allow' key will be set to false for both of these kinds of distributions:

<key>get-task-allow</key>
<false/>

However, 'Ad-Hoc' builds have a defined set of 'ProvisionedDevices'not present in 'App Store' builds:

<key>ProvisionedDevices</key>
<array>
<string>abcdef01234567890abcdef01234567890abacde</string>
<string>1abcdef01234567890abcdef01234567890abacd</string>
<string>2abcdef01234567890abcdef01234567890abacd</string>
</array>

So what does this mean in practical terms for the runtime checking question? Yes you can do it, by opening up the embedded.mobileprovision file out of the main bundle, and parsing data out of it to make an informed decision, but that is something you'd be entirely responsible for implementing yourself. You'll need to add logic to handle cases where that file is missing (ex. Simulator builds) and to either parse the PCKS#7 data or reliably extract the ASCII content of the file upon which your code can run a series of string searches. As is likely evident, this will require non-trivial effort for a somewhat brittle solution that can otherwise be easily accommodated by build settings and pre-processor macros at as Abhi Beckert outlined in the previous answer.

What about the risk of App Store rejection? Is this 'illegal' or 'subversive'?

Presuming that you use all public API when reading and parsing the contents of the embedded.mobileprovision file, this is perfectly allowable by the current terms of the App Store. Anything in your app's sandbox is fair game including embedded.mobileprovision if it happens to be present. I still strongly caution against going down this road, echoing Abhi Beckert's comments. It is a considerable amount of effort for less than 1% of use cases and there are far easier solutions out there! Furthermore, developer diagnostic views shouldn't be in App Store release builds, however the decision to include extraneous code is entirely in your hands.

I hope this clears up any lingering questions, but if not, please toss in a comment and we can see what we can do.

How to tell at runtime whether an iOS app is running through a TestFlight Beta install

For an application installed through TestFlight Beta the receipt file is named StoreKit/sandboxReceipt vs the usual StoreKit/receipt. Using [NSBundle appStoreReceiptURL] you can look for sandboxReceipt at the end of the URL.

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSString *receiptURLString = [receiptURL path];
BOOL isRunningTestFlightBeta = ([receiptURLString rangeOfString:@"sandboxReceipt"].location != NSNotFound);

Note that sandboxReceipt is also the name of the receipt file when running builds locally and for builds run in the simulator.

Swift Version:

let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"

How can I detect if the currently running app was installed from the app store?

Apps downloaded from the App Store have a iTunesMetadata.plist file added by the store:

NSString *file=[NSHomeDirectory() stringByAppendingPathComponent:@"iTunesMetadata.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:file]) {
// probably a store app
}

Perhaps you might want to check if this file exists.

Update:

In iOS8, the application bundle has been moved. According to @silyevsk, the plist is now one level above [the new application main bundle path], at /private/var/mobile/Containers/Bundle/Application/4A74359F-E6CD-44C9-925D-AC82E‌‌​​B5EA837/iTunesMetadata.plist, and unfortunately, this can't be accessed from the app (permission denied)

Update Nov 4th 2015:

It appears that checking the receipt name can help. It must be noted that this solution is slightly different: it doesn't return whether we're running an App Store app, but rather whether we're running a beta Testflight app. This might or might not be useful depending on your context.

On top of that, it's a very fragile solution because the receipt name could change at any time. I'm reporting it anyway, in case you have no other options:

// Objective-C
BOOL isRunningTestFlightBeta = [[[[NSBundle mainBundle] appStoreReceiptURL] lastPathComponent] isEqualToString:@"sandboxReceipt"];

// Swift
let isRunningTestFlightBeta = NSBundle.mainBundle().appStoreReceiptURL?.lastPathComponent=="sandboxReceipt"

Source: Detect if iOS App is Downloaded from Apple's Testflight

How HockeyKit does it

By combining the various checks you can guess whether the app is running in a Simulator, in a Testflight build, or in an AppStore build.

Here's a segment from HockeyKit:

BOOL bit_isAppStoreReceiptSandbox(void) {
#if TARGET_OS_SIMULATOR
return NO;
#else
NSURL *appStoreReceiptURL = NSBundle.mainBundle.appStoreReceiptURL;
NSString *appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent;

BOOL isSandboxReceipt = [appStoreReceiptLastComponent isEqualToString:@"sandboxReceipt"];
return isSandboxReceipt;
#endif
}

BOOL bit_hasEmbeddedMobileProvision(void) {
BOOL hasEmbeddedMobileProvision = !![[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
return hasEmbeddedMobileProvision;
}

BOOL bit_isRunningInTestFlightEnvironment(void) {
#if TARGET_OS_SIMULATOR
return NO;
#else
if (bit_isAppStoreReceiptSandbox() && !bit_hasEmbeddedMobileProvision()) {
return YES;
}
return NO;
#endif
}

BOOL bit_isRunningInAppStoreEnvironment(void) {
#if TARGET_OS_SIMULATOR
return NO;
#else
if (bit_isAppStoreReceiptSandbox() || bit_hasEmbeddedMobileProvision()) {
return NO;
}
return YES;
#endif
}

BOOL bit_isRunningInAppExtension(void) {
static BOOL isRunningInAppExtension = NO;
static dispatch_once_t checkAppExtension;

dispatch_once(&checkAppExtension, ^{
isRunningInAppExtension = ([[[NSBundle mainBundle] executablePath] rangeOfString:@".appex/"].location != NSNotFound);
});

return isRunningInAppExtension;
}

Source: GitHub - bitstadium/HockeySDK-iOS - BITHockeyHelper.m

A possible Swift class, based on HockeyKit's class, could be:

//
// WhereAmIRunning.swift
// https://gist.github.com/mvarie/63455babc2d0480858da
//
// ### Detects whether we're running in a Simulator, TestFlight Beta or App Store build ###
//
// Based on https://github.com/bitstadium/HockeySDK-iOS/blob/develop/Classes/BITHockeyHelper.m
// Inspired by https://stackoverflow.com/questions/18282326/how-can-i-detect-if-the-currently-running-app-was-installed-from-the-app-store
// Created by marcantonio on 04/11/15.
//

import Foundation

class WhereAmIRunning {

// MARK: Public

func isRunningInTestFlightEnvironment() -> Bool{
if isSimulator() {
return false
} else {
if isAppStoreReceiptSandbox() && !hasEmbeddedMobileProvision() {
return true
} else {
return false
}
}
}

func isRunningInAppStoreEnvironment() -> Bool {
if isSimulator(){
return false
} else {
if isAppStoreReceiptSandbox() || hasEmbeddedMobileProvision() {
return false
} else {
return true
}
}
}

// MARK: Private

private func hasEmbeddedMobileProvision() -> Bool{
if let _ = NSBundle.mainBundle().pathForResource("embedded", ofType: "mobileprovision") {
return true
}
return false
}

private func isAppStoreReceiptSandbox() -> Bool {
if isSimulator() {
return false
} else {
if let appStoreReceiptURL = NSBundle.mainBundle().appStoreReceiptURL,
let appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent
where appStoreReceiptLastComponent == "sandboxReceipt" {
return true
}
return false
}
}

private func isSimulator() -> Bool {
#if arch(i386) || arch(x86_64)
return true
#else
return false
#endif
}

}

Gist: GitHub - mvarie/WhereAmIRunning.swift

Update Dec 9th 2016:

User halileohalilei reports that "This no longer works with iOS10 and Xcode 8.". I didn't verify this, but please check the updated HockeyKit source (see function bit_currentAppEnvironment) at:

Source: GitHub - bitstadium/HockeySDK-iOS - BITHockeyHelper.m

Over time, the above class has been modified and it seems to handle iOS10 as well.

Update Oct 6th 2020:

Hockey has been deprecated/abandoned and replaced by Microsoft's AppCenter SDK.

This is their App Store / Testflight build detection class (link to repository below code):

MSUtility+Environment.h :

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#import <Foundation/Foundation.h>

#import "MSUtility.h"

/*
* Workaround for exporting symbols from category object files.
*/
extern NSString *MSUtilityEnvironmentCategory;

/**
* App environment
*/
typedef NS_ENUM(NSInteger, MSEnvironment) {

/**
* App has been downloaded from the AppStore.
*/
MSEnvironmentAppStore = 0,

/**
* App has been downloaded from TestFlight.
*/
MSEnvironmentTestFlight = 1,

/**
* App has been installed by some other mechanism.
* This could be Ad-Hoc, Enterprise, etc.
*/
MSEnvironmentOther = 99
};

/**
* Utility class that is used throughout the SDK.
* Environment part.
*/
@interface MSUtility (Environment)

/**
* Detect the environment that the app is running in.
*
* @return the MSEnvironment of the app.
*/
+ (MSEnvironment)currentAppEnvironment;

@end

MSUtility+Environment.m :

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#import "MSUtility+Environment.h"

/*
* Workaround for exporting symbols from category object files.
*/
NSString *MSUtilityEnvironmentCategory;

@implementation MSUtility (Environment)

+ (MSEnvironment)currentAppEnvironment {
#if TARGET_OS_SIMULATOR || TARGET_OS_OSX || TARGET_OS_MACCATALYST
return MSEnvironmentOther;
#else

// MobilePovision profiles are a clear indicator for Ad-Hoc distribution.
if ([self hasEmbeddedMobileProvision]) {
return MSEnvironmentOther;
}

/**
* TestFlight is only supported from iOS 8 onwards and as our deployment target is iOS 8, we don't have to do any checks for
* floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1).
*/
if ([self isAppStoreReceiptSandbox]) {
return MSEnvironmentTestFlight;
}

return MSEnvironmentAppStore;
#endif
}

+ (BOOL)hasEmbeddedMobileProvision {
BOOL hasEmbeddedMobileProvision = !![[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
return hasEmbeddedMobileProvision;
}

+ (BOOL)isAppStoreReceiptSandbox {
#if TARGET_OS_SIMULATOR
return NO;
#else
if (![NSBundle.mainBundle respondsToSelector:@selector(appStoreReceiptURL)]) {
return NO;
}
NSURL *appStoreReceiptURL = NSBundle.mainBundle.appStoreReceiptURL;
NSString *appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent;

BOOL isSandboxReceipt = [appStoreReceiptLastComponent isEqualToString:@"sandboxReceipt"];
return isSandboxReceipt;
#endif
}

@end

Source: GitHub - microsoft/appcenter-sdk-apple - MSUtility+Environment.m

Detect AppStore installation of iOS app

You can get part of the way there by reading in the embedded.mobileprovision file from the application bundle:

NSString *provisionPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];

If that does not exist, you are in an app store build.

If it does exist, you need to figure out some difference between your debug and ad-hoc provisioning profiles, and look for that to determine which build you are in.

Because XCode automatically sets up applications with a "DEBUG" flag in the Debug config, that is not set in Release (which is used by default for AdHoc builds), you may be better off disabling logging in an app store build and determining the level of logging based on the DEBUG macro flag.

Check if iOS app is live in app store

You can determine if your app was distributed via the app store by checking for the absence of embedded.mobileprovision. This file is only included in adhoc builds.

Like this:

if ([[NSBundle mainBundle] pathForResource:@"embedded"
ofType:@"mobileprovision"]) {
// not from app store (Apple's reviewers seem to hit this path)
} else {
// from app store
}

This technique is from the HockeyApp SDK. I personally have applications in the store that use this technique, and of course there are many apps distributed that include the HockeyApp SDK.

Based on an immediate crash I accidentally released in a particular build of my application in the "from app store" path, Apple's team will follow the "not from app store" path. Let my loss be your gain on that one. :)

Submitting Ad-hoc app to Appstore / iTunesConnect

There are a few targeted inner questions within your main question, I'll call attention to each part as we go -- as always, I'll be happy to revise or clarify if I miss something. I suppose it is only a closely guarded secret because much of the reasoning for it working come back to cryptographic details as a function of the Public Key Infrastructure system that backs Apple's provisioning -- This stuff gets deep fast so it is considered by some to be [dark] magic. Hopefully this will shine some light on what is going on!

TL;DR Version

Yes you can, but it is technically an unsupported use case that may change at any time. This works because what information iTunes Connect chooses to validate does not include the single differentiating factor between an App Store and AdHoc distribution provisioning profile. Since this is technically not a permitted configuration, I'd advocate for at least having a backup plan since Apple may change iTunes Connect validation policy at any time breaking this submission edge case.

Now for the curious, the here is the rest of the story...

Can you submit Adhoc-signed IPA to Appstore / iTunesConnect, and have it pass Apple verification and eventually be distributed through Appstore[?]

As of this specific iteration of iTunesConnect and the Application Loader (4 Sept 2014 / Xcode 5.1.1), yes you can submit an AdHoc signed build and have it accepted through the pipeline. The eagle-eyed reader will note that my 'Yes' comes with a built-in escape hatch -- Because of the data encoded in AdHoc vs App Store provisioning profiles is nearly identical coupled with what parts of these files iTunesConnect is actually using for validation, an AdHoc provisioning profile presents to the delivery pipeline in the same manner as the AppStore version of the same app.

Should the provisioning format change between AdHoc and App Store files to explicitly differentiate the two types of Distribution provisioning profiles or should Apple iTunesConnect engineers change server-side validation rules, it is distinctly possible that this undocumented behavior will stop working. Of course we all know that we are supposed to use the App Store provisioning profile, as per Developer documentation in the App Distribution Guide > Submitting Your App > About Store Provisioning Profiles (https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html#//apple_ref/doc/uid/TP40012582-CH9-SW32) [emphasis added]:

A store distribution provisioning profile contains a single App ID that matches one or more of your apps, and a distribution certificate. For iOS apps, you need a store provisioning profile to submit your app.

...but this other avenue works for now. If you do choose to use this avenue, you just need to be aware that it is not the documented behavior and thus would be subject to change at any point in time, likely without advanced notice. Since it is skirting the edges of submission requirements it would probably be good to at least have a backup plan setup for the case of Apple changing provisioning or iTC validation requirements -- Murphy's law would dictate that these validation changes would happen at the most inopportune time.

Stepping off the 'Best Practice' Soapbox and turning to the technical side of things...

Why [does this work]?

As you may or may not know, provisioning profiles are composed of exactly 1 appId, one or more signing certificates, and zero or more test devices.

Related Reading: I've got a longer answer to What are code signing identities? that speaks in more detail to the parts of the codesign process.

In this case the question is 'why do AdHoc profiles work when the documentation says you need to have an App Store profile?'

The guts of a provisioning profile contain a cryptographically signed .plist that includes the information identified above, plus some additional metadata. On an OS X machine you can open Terminal and run:

security cms -D -i path/to/AdHoc.mobileprovision

...and in a separate Terminal window run the App Store profile equivalent:

security cms -D -i path/to/AppStore.mobileprovison

These commands will dump out the plist portion of the provisioning profile to their respective Terminal windows. When you scroll through the contents of both windows you will note that the following sections are identical:

  • AppIDName
  • AppliationIdentifierPrefix
  • DeveloperCertificates
  • Entitlements
  • TeamIdentifier
  • Version

The profile's metadata are different, but those are entirely expected differences that only matter for validating profile validity, or for humans interrogating the profile:

  • CreationDate
  • ExpirationDate
  • Name
  • TimeToLive
  • UUID

The salient points to take away are:

  • The DeveloperCertificates blocks are identical between both profiles.
  • The AdHoc profile only adds information (ProvisionedDevices) to the structure and format of the App Store profile.

The contents of the DeveloperCertificates array is the DER encoded X.509 iPhone Distribution Certificate -- The exact same as the one in your keychain. Is is important to note that this DER data is only the public portion of your Distribution certificate public-private keypair, and it can only be used by others to authenticate the application's signature came from you -- It can not be used to resign a binary as you.

If you paste the contents of DeveloperCertificates:Array:Data element into an ASN.1 decoder (http://lapo.it/asn1js/) and compare the elements of the output to the information encoded in the Distribution certificate included in the Keychain, you'll find that it is an exact copy of the public Distribution certificate you downloaded from Apple after submitting your Certificate Signing Request though the Certificates, Identifiers, and Profiles tool.

Because both the AdHoc and App Store provisioning profiles use the same public key certificate as their signing identity, they are inherently using the same private key when generating the application's signature. This means that the signature generated when signing with an AdHoc profile is functionally identical to one generated when signing with the App Store profile

When Apple performs a signature validation on iTunes Connect during the submission process, both and AdHoc signed cryptographic signature and an App Store signed cryptographic signature will successfully validate against the Distribution Certificate Apple has on file as both provisioning profiles are backed by the same Distribution Certificate.

So the signatures match, but why doesn't the extra information in AdHoc profiles trip up the submission?

Your original question suggests that you have familiarity with iOS' app install policies. For the benefit of someone stumbling across this answer in the future I'll briefly summarize:

iOS operates on a 'deny-all unless specifically permitted' policy. That is, iOS assumes you are not allowed to install an app unless a specific 'grant' has been allowed. For devices coming from the App Store, the app's signature includes Apple's App Store identity for which iOS has a specific 'grant' privilege. AdHoc installs by default fall under the 'deny' policy and the ProvisionedDevices section of a Development or AdHoc profile are the specific 'grant' privileges. The app will install outside of the App Store if all of the following hold true:

  • The application's cryptographic signature is valid
  • The application's embedded provisioning profile's cryptographic signature is still valid (the profile hasn't been tampered with)
  • The application's embedded provisioning profile's ExpirationDate hasn't passed and the current time isn't before the CreationDate
  • The embedded profile or a profile installed to the device match the AppId being proposed for installation.
  • The embedded profile or a profile installed to the device contain an entry in ProvisionedDevices that exactly match the device's UDID.

As we saw above, the app identity and signing information is identical between an App Store profile and and Ad Hoc profile -- the addition of ProvisionedDevices serves only to add these 'grant' privileges for an external (outside of App Store) distribution mechanism. It turns out that iTunes Connect / Application Loader validation is currently only validating that a Distribution profile was used for the app's signature, not that the profile that was used was an App Store profile instead of an AdHoc profile.

This boils down to the fact that the as of Version 1 (ala Version block in the plist) the only differentiating factor between AdHoc and App Store distribution profiles is the presence or absence of the ProvisionedDevices block. It turns out that as of today, this is not a detail that Apple looks for when interrogating the profile that was used, thus the binary passes the automated portions of app verification.



Related Topics



Leave a reply



Submit