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.
Based on combinatorial's answer I created the following SWIFT helper class. With this class you can determine if it's a debug, testflight or appstore build.
enum AppConfiguration { case Debug case TestFlight case AppStore}struct Config { // This is private because the use of 'appConfiguration' is preferred. private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" // This can be used to add debug statements. static var isDebug: Bool { #if DEBUG return true #else return false #endif } static var appConfiguration: AppConfiguration { if isDebug { return .Debug } else if isTestFlight { return .TestFlight } else { return .AppStore } }}
We use these methods in our project to supply different tracking id's or connection string per environment:
func getURL(path: String) -> String { switch (Config.appConfiguration) { case .Debug: return host + "://" + debugBaseUrl + path default: return host + "://" + baseUrl + path } }
OR:
static var trackingKey: String { switch (Config.appConfiguration) { case .Debug: return debugKey case .TestFlight: return testflightKey default: return appstoreKey } }
UPDATE 05-02-2016:A prerequisite to use a preprocessor macro like #if DEBUG is to set some Swift Compiler Custom Flags. More information in this answer: https://stackoverflow.com/a/24112024/639227
Modern Swift version, which accounts for Simulators (based on accepted answer):
private func isSimulatorOrTestFlight() -> Bool { guard let path = Bundle.main.appStoreReceiptURL?.path else { return false } return path.contains("CoreSimulator") || path.contains("sandboxReceipt")}