对我有用的步骤:
将 Firebase 添加到应用扩展程序
通过 App Group 设置共享容器(或注册的 URL 方案等,此处不详述)
使用UserDefaults同步登录信息(或任何其他数据)
第 1 步:将 Firebase 添加到应用扩展程序
Firebase将应用扩展程序视为一个单独的应用程序,因此需要将其添加到主 Firebase 项目。
步骤:
- 将新的 iOS 应用添加到您现有的 Firebase 项目
- 将新的
GoogleService-Info.plist
拖到 Xcode 中的扩展中
- 将新目标添加到您的
Podfile
- 安装依赖项 (
pod install
)
- 在您的扩展程序中配置 Firebase 应用程序对象
请参阅此 SO 答案中的详细步骤。
步骤 2. 通过 App Group 设置共享容器
Firebase 项目中的应用相互隔离。例如,从应用程序扩展登录到项目的用户也必须登录包含的应用程序。检查Auth.auth().currentUser
只会产生特定上下文的结果。
Apple 官方指南(App Extension Programming Guide: Sharing Data with Your Containing App)展示了如何做到这一点,并用插图给出了很好的解释。
脚步:
创建新的应用组并配置 iOS 应用以使用它
在 Xcode 中为两个目标(即扩展和包含应用程序) 启用“应用程序组”功能
比如我们的主app是“ Access News ”:
共享扩展名为“ Access-News-Uploader ”:
确保将用户 ID 保存为默认值!Firebase 中的用户在项目级别进行处理,这使得用户可以通过项目中的任何应用程序登录(例如,一个用于包含应用程序,一个用于扩展程序),但这些状态仅用于实际保存正在使用的应用程序。例如,如果用户登录共享扩展并打开包含应用程序,如果包含应用程序Auth.auth().currentUser.uid
在任何时候调用它可能会产生nil
.
要使用单例和应用程序组共享数据UserDefaults
,请按照您需要它们的任何课程中的步骤操作:
let defaults = UserDefaults.init(suiteName: "group.your-app-group-id")!
使用其中一种功能设置默认值UserDefaults.set(...)
使用特定的getter查询值UserDefaults
例子
当我们的项目启动时,包含应用程序的 ( Access News ) 根视图控制器 ( NVC ) 检查"user-logged-in"
布尔UserDefaults
值(而不是 Auth.auth().currentUser
因为它只会显示包含应用程序的 Firebase 应用程序状态)。
(可以只保存用户 ID,并检查它是否存在,而不是同时使用 aBool
和String
key。)
// NVC.swift
import UIKit
import FirebaseAuth
class NVC: UINavigationController {
/* Step 1 */
let defaults = UserDefaults.init(suiteName: "group.org.societyfortheblind.access-news-reader-ag")!
/**********/
override func viewDidLoad() {
super.viewDidLoad()
/* Step 3 */
if self.defaults.bool(forKey: "user-logged-in") == false {
/**********/
let storyboard = UIStoryboard(name: "Main", bundle: .main)
let loginViewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
loginViewController.navigationItem.hidesBackButton = true
self.pushViewController(loginViewController, animated: false)
}
}
如果没有用户登录,LoginViewController
则加载true
成功登录时将密钥设置为。(在 中设置为false
注销SessionStartViewController
。)
// ViewController.swift
import UIKit
import FirebaseAuth
class LoginViewController: UIViewController {
/* Step 1 */
let defaults = UserDefaults.init(suiteName: "group.org.societyfortheblind.access-news-reader-ag")!
/**********/
// ...
@IBAction func tapSignInButton(_ sender: Any) {
// ...
Auth.auth().signIn(withEmail: username.text!, password: password.text!) {
(user, error) in
if error != nil {
// ...
} else {
/* Step 2 */
self.defaults.set(true, forKey: "user-logged-in")
// !!!
self.defaults.set(Auth.auth().currentUser.uid, forKey: "user-id")
/**********/
self.navigationController?.popViewController(animated: false)
}
}
}
}
在应用程序扩展中,在主导航控制器中检查了密钥,如果没有用户登录它,它将LoginViewController
从包含的应用程序加载。
// UploaderNavigationViewController.swift
import UIKit
import Firebase
class UploaderNavigationViewController: UINavigationController {
/* Step 1 */
let defaults = UserDefaults.init(suiteName: "group.org.societyfortheblind.access-news-reader-ag")!
/**********/
override func viewDidLoad() {
super.viewDidLoad()
if FirebaseApp.app() == nil {
FirebaseApp.configure()
}
/* Step 3 */
if self.defaults.bool(forKey: "user-logged-in") == false {
/**********/
let storyboard = UIStoryboard(name: "Main", bundle: .main)
let loginViewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
loginViewController.navigationItem.hidesBackButton = true
self.pushViewController(loginViewController, animated: false)
}
}
这是我们在提交时设置的项目。