Firebase app not being configured - ios

This randomly started happening and I cannot get passed it. My app crashes on launch with this in the debug area.
2016-10-29 14:31:57.606 gigMe[2285:73317] Firebase automatic screen reporting is enabled. Call +[FIRAnalytics setScreenName:setScreenClass:] to set the screen name or override the default screen class name. To disable automatic screen reporting, set the flag FirebaseAutomaticScreenReportingEnabled to NO in the Info.plist
2016-10-29 14:31:57.783 gigMe[2285] [Firebase/Core][I-COR000003] The default Firebase app has not yet been configured. Add [FIRApp configure] to your application initialization. Read more: gives google address that i cant post on here
2016-10-29 14:31:57.911 gigMe[2285:73317] * Terminating app due to uncaught exception 'FIRAppNotConfigured', reason: 'Failed to get default FIRDatabase instance. Must call FIRApp.configure() before using FIRDatabase.' * First throw call stack:
I really dont understand this at all because i havent messed with anything that has to do with the database and this is my didFinishLaunchingWithOptions method:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print("wtf")
FIRApp.configure()
return true
}
im not getting anything printed in the debugger either. anyone know what is going on?

This is not FIRApp.configure() error. You might be declaring a global variable with some class function in any of your class, like
class viewCon : UIViewController{
let ref = FIRDatabase.database().reference() // or a Storage reference
// This might be the error
}
The reason why this happens is because , you are trying to initialise a variable with a class function/property which might not even be configured as of yet. So try this:-
class viewCon : UIViewController{
let ref : FIRDatabaseReference!
// This might be the error or a Storage reference
override func viewDidLoad(){
super.viewDidLoad()
ref = FIRDatabase.database().reference()
}
}
To support above theory, try using breakpoints on let ref = FIRDatabase.database().reference() and FIRApp.configure(), and see which one gets called first. If let ref = FIRDatabase.database().reference() is called first , you are bound to have this error, as ref is trying to access FIRDatabase class, which hasn't been configured yet..

Related

Picture-in-picture in iOS fails with saying that the activationState is something other than foregroundActive but it is actually foregroundActive

I am implemeting Picture-in-picture on iOS. I added the background mode capability. When I call isPictureInPicturePossible, it returns false with error:
pictureInPictureController failedToStartPictureInPictureWithError Error Domain=AVKitErrorDomain Code=-1001 "Failed to start picture in picture." UserInfo={NSLocalizedDescription=Failed to start picture in picture., NSLocalizedFailureReason=The UIScene for the content source has an activation state other than UISceneActivationStateForegroundActive, which is not allowed.}
But I when I log the activationState, I can see that it is actually foregroundActive. Any idea what could be the reason?
(before that isPictureInPictureActive returns true, isPictureInPictureSuspended returns false, isPictureInPictureActive returns false.)
It is a little difficult to give an opinion without access to the code and without knowing the versions.
My suggestions:
Check if the app is really in the foreground. You can verify this by looking at the activationState of the UIScene for the content source. If it's not foregroundActive, you can't start the image in the image. If you are using a UISceneDelegate, you can check the activation state of the scene in the sceneWillEnterForeground: method. If using an AppDelegate, you can check the activation state of the scene in the applicationDidBecomeActive: method.
If you use using a UISceneDelegate instead of a AppDelegate. Change it to AppDelegate.
Set the sceneActivationState to foregroundActive in the AppDelegate.swift file:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
let scene = UIApplication.shared.connectedScenes.first
if let sceneDelegate = scene?.delegate as? SceneDelegate {
sceneDelegate.window?.windowScene?.activationState = .foregroundActive
}
}
return true
}
If no option to validate. We will give you more information about the problem.

Error: `call FirebaseApp.configure() before using Firestore`

Background Info
I have started developing a backend for an simple App, and I have set up a database class (named DBDelegate) that all the files will communicate with.
In my AppDelegate.swift I have this:
static public var dbDelegate:DBDelegate = DBDelegate()
private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
Its a static public so I can access the dbDelegate from other files.
In my other files, I have the following to help readability: (because it is a class it will pass by reference)
let dbDelegate = AppDelegate.dbDelegate
In my DBDelegate class:
var db = Firestore.firestore()
init() {
FirebaseApp.configure()
}
Building and Running
When I build my code, it builds fine.
On run, the app promptly crashes with SIGABRT.
The error message is:
Terminating app due to uncaught exception 'FIRAppNotConfiguredException', reason: 'Failed to get FirebaseApp instance. Please call FirebaseApp.configure() before using Firestore'
What I have tried
I have tried putting a breakpoint on the init function in the DBDelegate class. It does not reach the breakpoint.
I have tried making the all the dbDelegate variables lazy:
I got a compile error for the one in AppDelegate: lazy must not be used on an already-lazy global
Runtime errors for others: please call FirebaseApp.configure() before using Firestore.
I have tried the following (assigning dbDelegate in didFinishLaunchingWithOptions):
static public var dbDelegate:DBDelegate!
private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
dbDelegate = DBDelegate()
return true
}
I get Compile error: Static member 'dbDelegate' cannot be used on instance of type 'AppDelegate'
Any help would be great!
Edit: I found a janky solution, see below.
Firstly, I would like to thank #DionzB for suggesting using singletons (which I did). I will reference his/her post in this answer.
Ok, so after some research and playing with breakpoints, I found that my custom class actually executes before the AppDelegate. Knowing such, I created a variable before the following line:
static let shared = FirebaseService()
the name does not matter, because I/you will not call it, and assign it to FirebaseApp.configure()
The FirebaseService class becomes:
class FirebaseService: NSObject {
let constantToNeverTouch = FirebaseApp.configure()
static let shared = FirebaseService()
init() {
}
}
Next, you must make sure that FirebaseApp.configure() is no where else in your code. It should not be in the AppDelegate either. Having multiple FirebaseApp.configure()'s crashes the app.
You can override the AppDelegate init method with FirebaseApp.configure() and make sure it loads before any windows are created.
override init() {
FirebaseApp.configure()
}
It would be better to create a new singleton for Firebase.
class FirebaseService: NSObject {
static let shared = FirebaseService()
init() {
FirebaseApp.configure()
}
}
Then you can access everything via shared like:
FirebaseService.shared.methodName
For configuring in app delegate you would need to call it like:
_ = FirebaseService.shared
Chances are your code are in the wrong order. Make sure your window code are put AFTER the firebaseApp.configure and not before. I was getting the same crash until I simply placed my window creation codes: (window = UIWindow(frame: UIScreen.main.bounds), etc) after the firebaseApp.configure connection .Just swapped their placement:
FirebaseApp.configure()
let db = Firestore.firestore()
let settings = db.settings
settings.areTimestampsInSnapshotsEnabled = true
db.settings = settings
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = HomeController()
window?.makeKeyAndVisible()
I got the same issue because my pod version it old. So the solution is
Check your pods by using command pod --version
If pod the version is old or not the same, CocoaPods needs to update. Use comment sudo gem install CocoaPods
After it has completed you need to check your pods again use command pod --version make sure your pod version is upgraded
cd to your project directory then use command pod deintegrate
After the command completed then use pod install
Open your project workspace, build & run

Quickblox Webrtc Video Calling Swift - Documentation understanding

I am trying to integrate the Quickblox Webrtc Video Calling feature into a iOS Swift App. However, i'm having a lot of trouble with their SDK & api documentation, and it seems they don't have a tech team to help people with questions about their platforms, so maybe we can all help each other, so here are a few questions that I've noticed a lot of people have been asking on both StackOverFlow and Github regarding their webrtc SDK. Please restrict answers to the Swift language. The docs link is
http://quickblox.com/developers/SimpleSample-videochat-ios
My code so far:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//Firebase config
FIRApp.configure()
//Quickblox config
QBSettings.setApplicationID(xxxxx)
QBSettings.setAuthKey("xxxxxxxxxxx")
QBSettings.setAuthSecret("xxxxxxxx-xxxx")
QBSettings.setAccountKey("xxxxxxxxxxxxxxxxxxxx")
return true
}
Thats my appdelegate.swift now for the part that giving me problems the actual videochatviewcontroller. The documentation is very vague at the start all is says is:
// Initialize QuickbloxWebRTC and configure signaling
// You should call this method before any interact with
QuickbloxWebRTC QBRTCClient.initializeRTC() // Call this method when
you finish your work with QuickbloxWebRTC
QBRTCClient.deinitializeRTC()
I do not know if I am to call this in my appdelegate.swift or if I should call this in VideoChatViewController's viewDidLoad method or should I create a new method altogether?
Secondly,the docs say to CALL USERS use this method, but its not a method, just random variables, also it doesn't tell tell whether it goes to the viewDidLoad or to a newly created method :
QBRTCClient.instance().addDelegate(self) // self class must conform to QBRTCClientDelegate protocol
// 2123, 2123, 3122 - opponent's
let opponentsIDs = [3245, 2123, 3122]
let newSession = QBRTCClient.instance().createNewSessionWithOpponents(opponentsIDs, withConferenceType: QBRTCConferenceType.Video)
// userInfo - the custom user information dictionary for the call. May be nil.
let userInfo :[String:String] = ["key":"value"]
newSession.startCall(userInfo)
Next, they are vague regarding the method to receive a new session, below they refer to self.session which they never explain where this variable is from or what it consist of
func didReceiveNewSession(session: QBRTCSession!, userInfo: [NSObject : AnyObject]!) {
if self.session != nil {
// we already have a video/audio call session, so we reject another one
// userInfo - the custom user information dictionary for the call from caller. May be nil.
let userInfo :[String:String] = ["key":"value"]
session.rejectCall(userInfo)
}
else {
self.session = session
}
}
Does quickblox require authenticated Quickblox users to use their webrtc or can I Authenticate users with Firebase or parse?
Where do I use QBRTCConfig in the appdelegate or the viewDidLoad? I have tried both and have seen it used in both methods.

iOS swift You must specify clientID Exception in google integration

Code:
let signIn = GPPSignIn.sharedInstance()
signIn.shouldFetchGooglePlusUser = true
signIn.clientID = "912597493260-qg351fl8olmnmjl8qobos8n6u909jp0o.apps.googleusercontent.com"
signIn.scopes = [kGTLAuthScopePlusLogin];
signIn.trySilentAuthentication();
GIDSignIn.sharedInstance().signInSilently()
signIn.delegate = self
due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|
I double checked my code.Even i set client-id getting this exception.Where i went wrong?any help will be appreciated.thanks in advance
I was following Google's own guide for adding Sign-In here. I followed it step by step - integrated the google configuration file too. As per the guide, if the configuration file was included, setting the client id manually was not required. Unfortunately, I encountered exactly the same error when I run the app and hit the Sign-In button:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|'
Solution:
For some reason, clientID was not automatically picked from the configuration file. We should instead configure the GIDSignIn object directly, (using the client ID found in the GoogleService-Info.plist file) in the app delegate's application:didFinishLaunchingWithOptions: method:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
GIDSignIn.sharedInstance().clientID = "Cliend id From GoogleService-Info.plist file"
GIDSignIn.sharedInstance().delegate = self
return true
}
Also, if you are using Firebase, you can do it this way too:
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
It looks like the auto-generated config file, GoogleService-Info.plist, will include the wrong credentials by default; it includes the Web Client credentials instead of the iOS app credentials.
You need to correct the Client ID and the Reverse Client ID in the GoogleService-Info.plist.
Since these credentials are also used in your app's URLSchemes, you need to correct this there too.
I was also facing the same issue. I followed every step as per the documentation by https://firebase.google.com/docs/auth/ios/google-signin#swift_9 .
At last, I tried adding Client ID manually on my Controller's viewDidLoad and it worked after a long struggle.
Refer the code below. Replace your project specific Client-ID from GoogleService-info.plist in place of ClientID :
class IntroController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().clientID = "*ClientID*"
GIDSignIn.sharedInstance()?.presentingViewController = self
GIDSignIn.sharedInstance().signIn()
}
}
The clientId definitely does get picked up from the .plist file. If it appears not to be, it is likely that your code is attempting to use the sign-in object before it has been properly configured. Set a breakpoint on your configureWithError line, and make sure that it gets hit before any attempt to set a delegate, perform silent sign-in, etc.
Looks like the sign in method has now been updated by google, I was implementing the Google Calendar for iOS app and I found the following code for Sign In:
func applicationDidFinishLaunching(_ application: UIApplication) {
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError!)")
}
in their document which gave the same error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'You must specify |clientID| for |GIDSignIn|'
I took the lines which were inside:
func applicationDidFinishLaunching(_ application: UIApplication)
and put them in this method and sign in worked:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
Code for refernce:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Initialize sign-in
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError!)")
return true
}
You may need to obtain GoogleService-Info.plist from https://console.firebase.google.com rather than https://console.developers.google.com/.
Using Firebase remember also that you have to call Firebase.configure() function before you set the clientId. Otherwise, it won't work.

How do you save global arrays in the applicationWillTerminate and reload them in the application function?

So I have been trying to make an app for my Mobile Apps Development class and I need to find a solution to a problem that I'm having when I save a global array called "events".
Here I tried to reload the saved event class in AppDelegate but it didn't change in the main screen view controller:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Override point for customization after application launch.
//Load the events that were saved when application was terminated
let eventKey = NSUserDefaults.standardUserDefaults()
Global.events = (eventKey.arrayForKey("savedEvents") as? [Event])!
return true
}
Here is the function that is called when someone quits the app:
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
let myEvents = Global.events
NSUserDefaults.standardUserDefaults().setObject(myEvents, forKey: "savedEvents")
NSUserDefaults.standardUserDefaults().synchronize()
}
This might just be an error in the viewcontroller that displays this array but if you see something wrong with the code please let me know.
Two problems:
In iOS, there is no such thing as "someone quits the app", and thus what you're doing is unlikely to work, because applicationWillTerminate is never called. Save when the application is deactivated or backgrounded.
An array of Event cannot magically be saved in user defaults, because Event is not a Property List type. You will need to make Event archivable and archive the array.

Resources