Firebase 在启动时随机崩溃
Firebase crashing randomly on launch
我在 swift 中有一个 firebase 应用程序。现在我的问题解释起来很简单,但调试起来真的很奇怪。
问题:
每当我打开该应用程序时,它都可以正常运行。做它应该做的一切等等。但是当我将应用程序留在后台一段时间并打开它时,我遇到了崩溃。我必须重新打开它 2 次才能让崩溃消失或杀死它。
重现错误:
第 1 步:打开应用程序(在那里做一些事情或只是离开它)然后回到家中而不是杀死它,将其保留在后台
第2步:稍等片刻打开应用。 --- > 崩溃
第 3 步:在第 2 步之后一段时间后或立即再次打开它 --- > 再次崩溃
第四步:第三次打开。 ---> 工作得很好。
注意:为了避免崩溃,我总是要杀死它。这总体上是糟糕的用户体验。
此外,我已经检查过我的 plists。他们正常运作。然而当它崩溃时我得到这个错误:
2018-12-20 19:05:44.272413-0800 SpotMi[15557:862318] *** Terminating app due to uncaught exception 'FIRAppNotConfigured', reason: 'Failed to get default Firebase Database instance. Must call `[FIRApp configure]` (`FirebaseApp.configure()` in Swift) before using Firebase Database.'
*** First throw call stack:
(0x1a1e2bea0 0x1a0ffda40 0x1a1d32674 0x1030c8d20 0x102f9cd24 0x102f992b0 0x102f9926c 0x10f928dc8 0x10f92ae28 0x10ef95e18 0x102f9935c 0x102f49644 0x102f4a55c 0x102f4ad94 0x102e03b18 0x102d5cd4c 0x102f49260 0x102f493b0 0x102f4ac74 0x102f4b11c 0x102dbaf3c 0x102dbafd8 0x1cea6620c 0x1cea6663c 0x1cf0551e4 0x1cf051200 0x1cf0240a0 0x1cf02585c 0x1cf02b2a8 0x1ce8c7358 0x1ce8cffd8 0x1ce8c6fd4 0x1ce8c7974 0x1ce8c5a74 0x1ce8c5720 0x1ce8ca8e0 0x1ce8cb840 0x1ce8ca798 0x1ce8cf684 0x1cf0297a0 0x1cec12bac 0x1a48609d4 0x1a486b79c 0x1a486ae94 0x10f928dc8 0x10f92ca10 0x1a489fa9c 0x1a489f728 0x1a489fd44 0x1a1dbc1cc 0x1a1dbc14c 0x1a1dbba30 0x1a1db68fc 0x1a1db61cc 0x1a402d584 0x1cf02d054 0x102d5da9c 0x1a1876bb4)
libc++abi.dylib: terminating with uncaught exception of type NSException
应用代表:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
#if DEVELOPMENT
print("Development Mode Started")
let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")
guard let fileopts = FirebaseOptions.init(contentsOfFile: filePath!)
else {
fatalError("Couldn't load config file")
}
FirebaseApp.configure(options: fileopts)
#else
print("Production Mode Started")
FirebaseApp.configure()
#endif
return true
}
我尝试将此补丁放入 init()
,但随后通知停止工作。
我该如何解决这个问题。我做错了什么?
如果需要更多信息,请告诉我。
我的 firebase 单例如下:
class FBDataservice : NSObject {
static var ds = FBDataservice() //<-------- Always crahses on this line
let DB_URL: DatabaseReference = Database.database().reference()
let ST_URL: StorageReference = Storage.storage().reference()
private lazy var _REF_BASE = DB_URL
private lazy var _REF_POSTS = DB_URL.child("key1")
private lazy var _REF_USERS = DB_URL.child("key2")
private lazy var _ST_REF_PROFPOST = ST_URL.child("key3")
var REF_BASE: DatabaseReference! {
return _REF_BASE
}
var REF_POSTS: DatabaseReference! {
return _REF_POSTS
}
var REF_USERS: DatabaseReference! {
return _REF_USERS
}
var REF_POST_USERIMG: StorageReference {
return _ST_REF_USERPOST
}
}
AppDelegate 将初始化所有初始视图控制器(以及选项卡导航控制器中的所有主视图控制器)并在应用程序启动期间对它们调用 viewDidLoad()
。这是设计使然 (viewController's viewdidload called before appDelegate's method)
问题是在 init() 或 viewDidLoad()
方法中访问您的 ds
变量。这会导致在调用 FirebaseApp.configure()
和每个 viewDidLoad()
方法之间出现竞争条件。如果 FirebaseApp.configure()
在 viewcontroller 初始化之前完成,你会没事的。
要解决此问题,您需要自己接管故事板初始化。这需要两个步骤:
- Select 您的项目在 Xcode -> 常规中。向下滚动到主界面并将其删除
在您的 AppDelegate applicationDidFinishLaunching
方法中初始化所需的故事板,如下所示:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// configure Firebase
window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = storyboard.instantiateInitialViewController()
self.window?.makeKeyAndVisible()
return true
}
}
我假设连接到 Firebase 花费的时间太长,因此当您的代码中的依赖项得到满足时,应用程序不知道该做什么。您可以尝试将与连接相关的代码(Firebase.configure)放入try-catch块中以查看发生了什么。
我在 swift 中有一个 firebase 应用程序。现在我的问题解释起来很简单,但调试起来真的很奇怪。
问题: 每当我打开该应用程序时,它都可以正常运行。做它应该做的一切等等。但是当我将应用程序留在后台一段时间并打开它时,我遇到了崩溃。我必须重新打开它 2 次才能让崩溃消失或杀死它。
重现错误: 第 1 步:打开应用程序(在那里做一些事情或只是离开它)然后回到家中而不是杀死它,将其保留在后台
第2步:稍等片刻打开应用。 --- > 崩溃
第 3 步:在第 2 步之后一段时间后或立即再次打开它 --- > 再次崩溃
第四步:第三次打开。 ---> 工作得很好。
注意:为了避免崩溃,我总是要杀死它。这总体上是糟糕的用户体验。
此外,我已经检查过我的 plists。他们正常运作。然而当它崩溃时我得到这个错误:
2018-12-20 19:05:44.272413-0800 SpotMi[15557:862318] *** Terminating app due to uncaught exception 'FIRAppNotConfigured', reason: 'Failed to get default Firebase Database instance. Must call `[FIRApp configure]` (`FirebaseApp.configure()` in Swift) before using Firebase Database.'
*** First throw call stack:
(0x1a1e2bea0 0x1a0ffda40 0x1a1d32674 0x1030c8d20 0x102f9cd24 0x102f992b0 0x102f9926c 0x10f928dc8 0x10f92ae28 0x10ef95e18 0x102f9935c 0x102f49644 0x102f4a55c 0x102f4ad94 0x102e03b18 0x102d5cd4c 0x102f49260 0x102f493b0 0x102f4ac74 0x102f4b11c 0x102dbaf3c 0x102dbafd8 0x1cea6620c 0x1cea6663c 0x1cf0551e4 0x1cf051200 0x1cf0240a0 0x1cf02585c 0x1cf02b2a8 0x1ce8c7358 0x1ce8cffd8 0x1ce8c6fd4 0x1ce8c7974 0x1ce8c5a74 0x1ce8c5720 0x1ce8ca8e0 0x1ce8cb840 0x1ce8ca798 0x1ce8cf684 0x1cf0297a0 0x1cec12bac 0x1a48609d4 0x1a486b79c 0x1a486ae94 0x10f928dc8 0x10f92ca10 0x1a489fa9c 0x1a489f728 0x1a489fd44 0x1a1dbc1cc 0x1a1dbc14c 0x1a1dbba30 0x1a1db68fc 0x1a1db61cc 0x1a402d584 0x1cf02d054 0x102d5da9c 0x1a1876bb4)
libc++abi.dylib: terminating with uncaught exception of type NSException
应用代表:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
#if DEVELOPMENT
print("Development Mode Started")
let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")
guard let fileopts = FirebaseOptions.init(contentsOfFile: filePath!)
else {
fatalError("Couldn't load config file")
}
FirebaseApp.configure(options: fileopts)
#else
print("Production Mode Started")
FirebaseApp.configure()
#endif
return true
}
我尝试将此补丁放入 init()
,但随后通知停止工作。
我该如何解决这个问题。我做错了什么?
如果需要更多信息,请告诉我。
我的 firebase 单例如下:
class FBDataservice : NSObject {
static var ds = FBDataservice() //<-------- Always crahses on this line
let DB_URL: DatabaseReference = Database.database().reference()
let ST_URL: StorageReference = Storage.storage().reference()
private lazy var _REF_BASE = DB_URL
private lazy var _REF_POSTS = DB_URL.child("key1")
private lazy var _REF_USERS = DB_URL.child("key2")
private lazy var _ST_REF_PROFPOST = ST_URL.child("key3")
var REF_BASE: DatabaseReference! {
return _REF_BASE
}
var REF_POSTS: DatabaseReference! {
return _REF_POSTS
}
var REF_USERS: DatabaseReference! {
return _REF_USERS
}
var REF_POST_USERIMG: StorageReference {
return _ST_REF_USERPOST
}
}
AppDelegate 将初始化所有初始视图控制器(以及选项卡导航控制器中的所有主视图控制器)并在应用程序启动期间对它们调用 viewDidLoad()
。这是设计使然 (viewController's viewdidload called before appDelegate's method)
问题是在 init() 或 viewDidLoad()
方法中访问您的 ds
变量。这会导致在调用 FirebaseApp.configure()
和每个 viewDidLoad()
方法之间出现竞争条件。如果 FirebaseApp.configure()
在 viewcontroller 初始化之前完成,你会没事的。
要解决此问题,您需要自己接管故事板初始化。这需要两个步骤:
- Select 您的项目在 Xcode -> 常规中。向下滚动到主界面并将其删除
在您的 AppDelegate
applicationDidFinishLaunching
方法中初始化所需的故事板,如下所示:class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // configure Firebase window = UIWindow(frame: UIScreen.main.bounds) let storyboard = UIStoryboard(name: "Main", bundle: nil) window?.rootViewController = storyboard.instantiateInitialViewController() self.window?.makeKeyAndVisible() return true } }
我假设连接到 Firebase 花费的时间太长,因此当您的代码中的依赖项得到满足时,应用程序不知道该做什么。您可以尝试将与连接相关的代码(Firebase.configure)放入try-catch块中以查看发生了什么。