如何在运行时判断 iOS 应用程序是否正在通过 TestFlight Beta 安装运行

是否可以在运行时检测到通过 TestFlight Beta (通过 iTunes Connect 提交)和 App Store 安装的应用程序?您可以提交一个单独的应用程序包,并通过两者提供它。是否有一个 API 可以检测它是以哪种方式安装的?或者收据是否包含可以确定这一点的信息?

35450 次浏览

对于通过 TestFlight Beta 安装的应用程序,收据文件命名为 StoreKit/sandboxReceipt,而不是通常的 StoreKit/receipt。使用 [NSBundle appStoreReceiptURL],您可以在 URL 的末尾查找 sandboxReceipt。

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

请注意,在本地运行构建和在模拟器中运行构建时,sandboxReceipt也是接收文件的名称。

迅速版本:

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

基于 组合答案,我创建了以下 SWIFT 助手类。使用这个类,您可以确定它是调试、测试飞行还是应用程序商店构建。

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
}
}
}

在我们的项目中,我们使用这些方法为每个环境提供不同的 追踪身份连接字符串:

  func getURL(path: String) -> String {
switch (Config.appConfiguration) {
case .Debug:
return host + "://" + debugBaseUrl + path
default:
return host + "://" + baseUrl + path
}
}

或者:

  static var trackingKey: String {
switch (Config.appConfiguration) {
case .Debug:
return debugKey
case .TestFlight:
return testflightKey
default:
return appstoreKey
}
}

更新05-02-2016: 使用预处理器宏(如 # if DEBUG)的先决条件是设置一些 Swift 编译器自定义标志。更多信息请点击: http://stackoverflow/a/24112024/639227 https://stackoverflow.com/a/24112024/639227

现代斯威夫特版本,其帐户模拟器(基于接受的答案) :

private func isSimulatorOrTestFlight() -> Bool {
guard let path = Bundle.main.appStoreReceiptURL?.path else {
return false
}
return path.contains("CoreSimulator") || path.contains("sandboxReceipt")
}

在我的项目中有一种使用它的方法。

在 Xcode,进入项目设置(project,而不是 target)并在列表中添加“ beta”配置:

enter image description here



然后你需要创建一个新的方案,这个方案将以“ beta”配置运行项目:

enter image description here



你可以随意命名这个方案。你应该编辑这个方案的设置。要做到这一点,点击这里:

enter image description here



选择 Archive 选项卡,在其中可以选择 Build configuration

enter image description here



然后,您需要添加一个键 Config与值 $(CONFIGURATION)的项目信息属性列表如下:

enter image description here



那么问题就在于你需要在代码中做一些特定于 beta 版本的事情:

let config = Bundle.main.object(forInfoDictionaryKey: "Config") as! String
if config == "Debug" {
// app running in debug configuration
}
else if config == "Release" {
// app running in release configuration
}
else if config == "Beta" {
// app running in beta configuration
}

我在 Swift 5.2上使用扩展 Bundle+isProduction:

import Foundation


extension Bundle {
var isProduction: Bool {
#if DEBUG
return false
#else
guard let path = self.appStoreReceiptURL?.path else {
return true
}
return !path.contains("sandboxReceipt")
#endif
}
}

然后:

if Bundle.main.isProduction {
// do something
}