我有三个API
具有不同的API Keys
和一些不同的设置
用于开发或内部测试构建 - iOS App Store外的开发分发
Host
- devapi.project-name.com API Key
- development_key FLEX
[1] - 启用对于客户端测试构建 - iOS App Store外的企业分发
Host
- stgapi.project-name.com API Key
- enterprise_key FLEX
- 启用适用于生产版本 - 在iOS App Store中分发
Host
- api.project-name.com API key
- app_store_key FLEX
- 停用我可以使用DEBUG
#if DEBUG
#define API_BASE_URL @"http://devapi.project-name.com/api/v1"
#define API_KEY @"development_key"
#else
#define API_BASE_URL @"http://stgapi.project-name.com/api/v1"
#define API_KEY @"enterprise_key"
#endif
// In AppDelegate.m
#if DEBUG
[[FLEXManager sharedManager] showExplorer];
#endif
但第一个问题是企业分发(用于客户端测试)和iOS 适用于企业和应用程序的App Store分发(生产)构建 每次需要更改代码时的商店分发
适用于企业分发
#if DEBUG
//debug setting
#else
//enterprise setting
#define API_BASE_URL @"http://stgapi.project-name.com/api/v1"
#define API_KEY @"enterprise_key"
#endif
适用于App Store分发
#if DEBUG
//debug setting
#else
//app store setting
#define API_BASE_URL @"http://api.project-name.com/api/v1"
#define API_KEY @"app_store_key"
#endif
我正在寻找像这样的东西
#ifdef DEVELOPMENT
#define API_BASE_URL @"http://devapi.project-name.com/api/v1"
#define API_KEY @"development_key"
#elif ENTERPRISE
#define API_BASE_URL @"http://stgapi.project-name.com/api/v1"
#define API_KEY @"enterprise_key"
#elif APP_STORE
#define API_BASE_URL @"http://api.project-name.com/api/v1"
#define API_KEY @"app_store_key"
#endif
或其他任何?
第二个问题
有没有办法在不创建不同目标的情况下创建具有不同名称的三个构建?
ProductName
- 适用于App Store ProductName-Dev
- 内部开发构建ProductName-Stg
- 用于客户端测试(企业)构建我刚刚根据iamnichols提供的解决方案创建了演示项目和完整的视觉指南
答案 0 :(得分:13)
调试和发布版本之间的区别在于,一个存档并导出但另一个在调试器中通过Xcode本地运行。您可能会发现您有时希望在调试器中运行生产或暂存构建,但是通过#ifdef DEBUG
拆分东西,您可能会遇到问题。
这是我所做的简化版本:
在项目(非目标)设置中,创建(从原件复制)以下配置:
请注意,如果您使用Cocoapods,则需要将配置设置为none,删除项目中Pods文件夹的内容( Not the Pods project )并重新运行{{ 1}}。
不是仅仅拥有MyApp方案,而是创建以下内容(复制原始内容):
在每个方案中,在适当的地方使用关联的Debug_ *和Release_ *配置。
添加一个额外的预处理器宏,以确定您正在构建的环境。
在项目构建设置中,单击+并添加用户定义的构建设置,并将其称为pod install
。然后,对于每个不同的环境组,为每个环境添加不同的预处理器宏。即MYAPP_ENVIRONMENT
,ENV_DEV=1
和ENV_STAGING=1
。
然后,在c预处理器宏中(再次在项目级别而不是目标级别)使用ENV_PROD=1
添加此新的MYAPP_ENVIRONMENT设置。
这样,您就可以确定要构建的环境,如下所示:
$(MYAPP_ENVIRONMENT)
这可能需要很多,但请告诉我你是如何继续的。
然后,您还可以创建不同的用户定义构建设置来执行不同的操作,例如更改应用的显示名称。
您可以通过创建名为#ifdef ENV_DEV
NSString * const MyAppAPIBaseURL = @"https://api-dev.myapp.com/";
#elif ENV_SAGING
NSString * const MyAppAPIBaseURL = @"https://api-staging.myapp.com/";
#elif ENV_PROD
NSString * const MyAppAPIBaseURL = @"https://api.myapp.com/";
#endif
的新设置来执行此操作,例如,为每个配置设置正确的名称,然后在MYAPP_DISPLAY_NAME
中将Bundle Display Name的值设置为{{1} }。
答案 1 :(得分:0)
更简单且不太复杂的解决方案是为每个配置使用不同的头文件,并且#importing只有其中一个。这不是自动的,但它很简单:
// You only need to switch the following lines when passing from qa 2 production and back:
#import "Mode_QA.h"
//#import "Mode_Production.h"
答案 2 :(得分:0)
1)创建(或重复)目标
OR
我的样品:
我复制了现有目标并将其重命名。我的目标名称:
2)组织并重命名信息访问者
我将所有plists放在一个文件夹中: info.plists
3)重命名构建方案
4)检查构建方案参数
按下编辑按钮
检查您的构建方案是否已连接到正确的目标。
我的样本:
App-Development构建方案(在下图的左上角看到)连接到 App-Development目标(目标位于下图的中心) )。
还要检查可执行应用程序。
我的样品:
5)向信息访问者添加值
我的样品:
Info-Production.plist
<key>LSEnvironment</key>
<dict>
<key>Environment</key>
<string>Production</string>
<key>Host</key>
<string>https://production.host.com</string>
<key>AppID</key>
<integer>1</integer>
<key>AdvertisementEnabled</key>
<true/>
</dict>
Info-Development.plist
<key>LSEnvironment</key>
<dict>
<key>Environment</key>
<string>Development</string>
<key>Host</key>
<string>https://development.host.com</string>
<key>AppID</key>
<integer>2</integer>
<key>AdvertisementEnabled</key>
<false/>
</dict>
Info-Staging.plist
<key>LSEnvironment</key>
<dict>
<key>Environment</key>
<string>Staging</string>
<key>Host</key>
<string>https://staging.host.com</string>
<key>AppID</key>
<integer>3</integer>
<key>AdvertisementEnabled</key>
<false/>
</dict>
Environment.swift
import Foundation
// MARK: - Environment main class
class Environment {
class Value { private init(){} }
class Enums { private init(){} }
}
extension Environment.Value {
static var all: [String: Any] {
return Bundle.main.infoDictionary?["LSEnvironment"] as? [String: Any] ?? [:]
}
}
extension Environment.Value {
private enum Keys: String {
case environment = "Environment"
case host = "Host"
case appID = "AppID"
case advertisementEnabled = "AdvertisementEnabled"
}
private static func get<T>(value key: Keys, type: T.Type) -> T? {
return all[key.rawValue] as? T
}
}
// MARK: - Environment type value
extension Environment.Enums {
enum EnvironmentType: String {
case production = "Production"
case staging = "Staging"
case development = "Development"
}
}
extension Environment.Value {
static var type: Environment.Enums.EnvironmentType {
let environment = get(value: .environment, type: String.self)!
return Environment.Enums.EnvironmentType(rawValue: environment)!
}
}
// MARK: - Host (sample with string)
extension Environment.Value {
static var host: String { return get(value: .host, type: String.self)! }
}
// MARK: - App ID (sample with number)
extension Environment.Value {
static var appID: Int { return get(value: .appID, type: Int.self)! }
}
// MARK: - Advertisement Enabled (sample with bool)
extension Environment.Value {
static var advertisementEnabled: Bool { return get(value: .advertisementEnabled, type: Bool.self)! }
}
print("All values: \(Environment.Value.all)")
switch Environment.Value.type {
case .development: print("Environment: dev")
case .staging: print("Environment: stage")
case .production: print("Environment: prod")
}
print("Host: \(Environment.Value.host)")
print("App ID: \(Environment.Value.appID)")
print("Advertisement Enabled: \(Environment.Value.advertisementEnabled)")
当您运行一种构建方案时,您将具有不同的值。
选择构建方案
运行