在新的 Firebase 中,如何在 xcode 中使用多个配置文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37472090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In new Firebase, how to use multiple config file in xcode?
提问by coolbeet
Hey I am playing with the new firebase iOS SDK, in my project, I have only one target, I created two configurations, Debug and Release, with different bundler identifier, but seems like the config file downloaded from firebase only support one bundle identifier.
嘿,我正在玩新的 firebase iOS SDK,在我的项目中,我只有一个目标,我创建了两个配置,Debug 和 Release,具有不同的 bundler identifier,但似乎从 firebase 下载的配置文件只支持一个 bundle identifier。
So anyone know how to use firebase within a multiple bundle identifier xcode project?
那么有人知道如何在多包标识符 xcode 项目中使用 firebase 吗?
Thanks!
谢谢!
回答by Chris Chen
Update: see Firebase official documentationhttps://firebase.google.com/docs/projects/multiprojects
更新:请参阅 Firebase 官方文档https://firebase.google.com/docs/projects/multiprojects
Updated with an easier solution:
更新了一个更简单的解决方案:
1. keep the same names for both GoogleService-Info.plist
2. put one GoogleService-Info.plist inside a subfolder, say "staging"
3. add references to both files in Xcode while linking them to corresponding targets
4. just use FIRApp.configure() in your AppDelegate, done
My first attempt that didn't solve the issue:
我的第一次尝试没有解决问题:
I renamed the second GoogleService-Info.json to something else and used following code to configure Firebase from AppDelegate.
我将第二个 GoogleService-Info.json 重命名为其他内容,并使用以下代码从 AppDelegate 配置 Firebase。
// Swift code
#if STAGING
let firebasePlistFileName = "GoogleService-Staging-Info"
#else
let firebasePlistFileName = "GoogleService-Info"
#endif
let firbaseOptions = FIROptions(contentsOfFile: NSBundle.mainBundle().pathForResource(firebasePlistFileName, ofType: "plist"))
FIRApp.configureWithOptions(firbaseOptions)
If I run the Staging target, I will receive Firebase's complaint about 'Could not locate configuration file: 'GoogleService-Info.plist'.'. But then it says ' Firebase Analytics v.3300000 started'.
如果我运行 Staging 目标,我会收到 Firebase 关于“找不到配置文件:'GoogleService-Info.plist'.”的投诉。但随后它说“ Firebase Analytics v.3300000 已启动”。
As I checked on the Firebase dashboard, both production and staging apps have incoming user events being logged.
当我在 Firebase 仪表板上检查时,生产应用程序和暂存应用程序都记录了传入的用户事件。
The above-mentioned configureWithOptions method is not documented in Firebase documentation, I figured it out by checking its source code. I'm not sure about what could be the downside of calling this. I would love to hear other approaches.
上面提到的 configureWithOptions 方法没有记录在 Firebase 文档中,我通过检查它的源代码弄清楚了。我不确定调用它的缺点是什么。我很想听听其他方法。
回答by Chris Conway
I've implemented something similar, as I've had two schemes for a single target that have different bundle identifiers. In my examples below, I have two different schemes, one for UAT and one for PROD.
我已经实现了类似的东西,因为我已经为具有不同包标识符的单个目标提供了两种方案。在下面的示例中,我有两种不同的方案,一种用于 UAT,一种用于 PROD。
Create the two GoogleService-Info.json files, and put them into your project directory (not Xcode project) in different folders, e.g.
创建两个 GoogleService-Info.json 文件,并将它们放入您的项目目录(不是 Xcode 项目)的不同文件夹中,例如
ROOT/config/UAT/GoogleService-Info.json
ROOT/config/PROD/GoogleService-Info.json
Then add the files to your Xcode project like so:
然后将文件添加到您的 Xcode 项目中,如下所示:
Now you need to add a Run Script in your Build Phases. This will need to be added before the Compile Sources stage:
现在您需要在您的构建阶段添加一个运行脚本。这将需要在 Compile Sources 阶段之前添加:
This Run Script takes the appropriately located json file and duplicates it into the build app directory, meaning Firebase/Google will identify it identically to how it would identify the file in a single identifier setup.
此运行脚本获取适当位置的 json 文件并将其复制到构建应用程序目录中,这意味着 Firebase/Google 将对其进行识别,以与在单个标识符设置中识别文件的方式相同。
isUAT=`expr "$GCC_PREPROCESSOR_DEFINITIONS" : ".*UAT=\([0-9]*\)"`
RESOURCE_PATH=${SRCROOT}/${PRODUCT_NAME}/config/PROD
if [ $isUAT = 1 ]; then
RESOURCE_PATH=${SRCROOT}/${PRODUCT_NAME}/config/UAT
fi
BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo "Copying all files under ${RESOURCE_PATH} to ${BUILD_APP_DIR}"
cp -v "${RESOURCE_PATH}/"* "${BUILD_APP_DIR}/"
I would estimate you can use this same logic for Google Analytics as well, which uses a similar json config file setup.
我估计您也可以对 Google Analytics 使用相同的逻辑,它使用类似的 json 配置文件设置。
回答by TheiOSChap
Better approach if you have single target is to just name your configs appropriately and load them as below. Seems to work fine for UAT environment example : Swift 3.0
如果您只有一个目标,更好的方法是适当地命名您的配置并按如下方式加载它们。似乎适用于 UAT 环境示例:Swift 3.0
var fireBaseConfigFile = Bundle.main.path(forResource: "GoogleService-Info-PROD", ofType: "plist")
#if UAT
fireBaseConfigFile = Bundle.main.path(forResource: "GoogleService-Info-UAT", ofType: "plist")
#endif
guard let firOptions = FIROptions(contentsOfFile: fireBaseConfigFile) else {
assert(false, "Failed to load Firebase config file")
return
}
FIRApp.configure(with: firOptions)
回答by vikzilla
Add both Google Service plists to your project, with different names:
将两个 Google Service plist 添加到您的项目中,使用不同的名称:
Then for each Build Scheme, select Edit Scheme and add a unique value for an environment variable like so:
然后对于每个构建方案,选择编辑方案并为环境变量添加一个唯一值,如下所示:
So the other build scheme's BUILD_FOR environment variable would be set to "DEV", for example.
例如,其他构建方案的 BUILD_FOR 环境变量将设置为“DEV”。
Then, you would check for this variable in App Delegate and configure the FIRApp according to which scheme was built:
然后,您将在 App Delegate 中检查此变量并根据构建的方案配置 FIRApp:
let buildFor = ProcessInfo.processInfo.environment["BUILD_FOR"]! as String
var firebasePlistFileName = "GoogleService-Info"
if buildFor == "PROD" {
firebasePlistFileName = "GoogleService-Prod-Info"
}
let firbaseOptions = FIROptions(contentsOfFile: Bundle.main.path(forResource: firebasePlistFileName, ofType: "plist"))
FIRApp.configure(with: firbaseOptions!)
回答by Tai Le
I did store 2 GoogleService-Info with different names:
我确实存储了 2 个不同名称的 GoogleService-Info:
GoogleService-Info.plist
for productionGoogleService-Info-Debug.plist
for development
GoogleService-Info.plist
用于生产GoogleService-Info-Debug.plist
发展
And then go to Build Phases
, add new run script:
然后转到Build Phases
,添加新的运行脚本:
if [ "${CONFIGURATION}" == "Release" ]; then
cp -r "${PROJECT_DIR}/PathToYourGoogleServiceInfoFile/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
echo "Production plist copied"
elif [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/PathToYourGoogleServiceInfoFile/GoogleService-Info-Debug.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
echo "Development plist copied"
fi
回答by Bruno Lemos
Using Objective-C, in your AppDeletage.m:
在你的 AppDeletage.m 中使用 Objective-C:
NSString *filePath;
#ifdef DEBUG
filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Debug" ofType:@"plist"];
#else
filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Production" ofType:@"plist"];
#endif
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
回答by levibostian
Firebase includes official documentationfor how to do this now. I used this method in my app and it works great.
Firebase 现在包含有关如何执行此操作的官方文档。我在我的应用程序中使用了这种方法,效果很好。
More specifically, I defined a custom Swift flag "BUILD_TYPE" in XCode and for each scheme, I define a unique value for that flag. Then, in my AppDelegate, I tell Firebase what GoogleService-___.plist
file to load at runtime by this Swift flag value:
更具体地说,我在 XCode 中定义了一个自定义 Swift 标志“BUILD_TYPE”,并且对于每个方案,我为该标志定义了一个唯一值。然后,在我的 AppDelegate 中,我GoogleService-___.plist
通过这个 Swift 标志值告诉 Firebase在运行时加载哪个文件:
let filePath = Bundle.main.path(forResource: "GoogleService-" + Bundle.main.infoDictionary!["BUILD_FLAVOR"] as! String, ofType: "plist")
guard let fileopts = FirebaseOptions.init(contentsOfFile: filePath!) else {
fatalError("Couldn't load config file")
}
FirebaseApp.configure(options: fileopts)
回答by RodolfoAntonici
I see a lot of responses using Targets, but if you want to differentiate by scheme you can go to:
我看到很多使用 Targets 的回复,但如果你想按方案区分,你可以去:
Edit Schemes... > Select Scheme > Build > Post-Action
编辑方案... > 选择方案 > 构建 > 动作后
- Add a Run Script
- Provide build settings from: (select the target you want to)
- Add following script
- 添加运行脚本
- 从以下位置提供构建设置:(选择您想要的目标)
- 添加以下脚本
PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/MVCVMRC/Supporting Files/FirebasePlist"
cp -r "$PATH_TO_GOOGLE_PLISTS/Brazil/GoogleService-Info-preprod.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
Don't forget to change the PATH_TO_GOOGLE_PLISTS
不要忘记更改 PATH_TO_GOOGLE_PLISTS
回答by Hemant Sharma
The latest syntax is here to configure firebase for 2 targets (2 Plist files)
最新语法在这里为 2 个目标(2 个 Plist 文件)配置 firebase
func configureFirebase() {
let firebasePlistFileName = ConfigurationManager.sharedManager().firebasePlistName()
if let path = Bundle.main.path(forResource: firebasePlistFileName, ofType: "plist") {
if let firbaseOptions = FirebaseOptions(contentsOfFile: path) {
FirebaseApp.configure(options: firbaseOptions)
}
}
}
firebasePlistFileNamevariable is just fetching the PList name based on current configuration i.e. Development or Production.
firebasePlistFileName变量只是根据当前配置(即开发或生产)获取 PList 名称。