Error with appDelegate while testing firebase based app - swift

Im trying to do some snapshot tests on my firebase based app.
I made some snapshot tests with 'LogInVC' it worked well because it has nothing in common with firebase but then, after LoginTests I've tried to test tableView that should be shown after successful login:
First I made "TestingAppDelegate" in test target:
import UIKit
#objc(TestingAppDelegate)
class TestingAppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
print(">> Launching with testing app delegate")
return true
}
To avoid the regular app delegate during testing I made a code in a file called "main" that tries to find a class named TestingAppDelegate made in "Testing" target and also deleted #main in regular AppDelegate.
import UIKit
let appDelegateClass: AnyClass =
NSClassFromString("TestingAppDelegate") ?? AppDelegate.self
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil,
NSStringFromClass(appDelegateClass))
This is how my test looks:
class UsersTests: XCTestCase {
var sut: AllUsersViewController!
override func setUp() {
sut = AllUsersViewController()
sut.loadViewIfNeeded()
}
override func tearDown() {
sut = nil
}
func testInitialLoginScreen(){
setUsers()
assertSnapshot(matching: sut, as: .image, record: true)
}
func setUsers(){
for number in 0...5{
let user = UserInfo(firstName: "Nikola", lastName: "Andr", username: "lol", pictureURL: nil, training: ["lol","mma"], uid: "\(number)", admin: false)
sut.users.append(user)
}
}
When I run tests this is error I get in "main" file that switches app delegates.
"The default FirebaseApp instance must be configured before the
default Authinstance can be initialized. One way to ensure this is to
call FirebaseApp.configure() in the App Delegate's
application(_:didFinishLaunchingWithOptions:) (or the #main
struct's initializer in SwiftUI)."
I've never tested firebase app before so I don't know that to do now. Any reference where to learn about how to test firebase apps will be helpful too.

Related

How do i connect the firebase Firestore to my swift app

I have tried many different resources online but they all seem to use app delegate files and I get TOTALLY confused.
All I want to be able to do is read and write from the cloud firestore to my swift app
I have installed firebase and the firestore via the package manager and it can't seem to find the Firestore Manager
import SwiftUI
import Firebase
#main
struct RecipyApp: App{
#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#StateObject var firestoreManager = FirestoreManager()
var body: some Scene{
let viewModel = AppViewModel()
WindowGroup{
ContentView()
.environmentObject(viewModel)
.environmentObject(firestoreManager)
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
MY CODE.
What can I do to fix my problem?
Many thanks
Solution 1:
Delete The Excess Package And Run The App
Solution 2:
Go To Xcode Preference > Location, Delete Derived Data

Thread1: signal SIGABRT

I am getting Thread 1: signal SIGABRT error on appDelegate, I think it is because of facebook login button which I have been trying to connect to my xcode project through facebook sdk. I dont know if the way i am connecting facebook login button through outlet is correct or not. because at first it was giving me an error of optional unwrapping, when I avoided it by adding ? in the code below
fbloginbtnview?.delegate = self
fbloginbtnview?.permissions = ["email"]
now I get signal SIGABRT error.
I have been watching all the tutorials and reading all the questions on stackoverflow, but can not find anything helpful to connect facebook login button, because al the helps available are either for older versions of swift and xcode or I dont get axactly what i want.
my swift version is 5, and xcode 9.3
can anyone please give me a right peice of code to connect a facebook login button?
This is appdelegate
import UIKit
import Firebase
import CoreData
import FirebaseAuth
import FacebookCore
import FBSDKCoreKit
import FBSDKLoginKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
//below for fb sdk
//....
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
//....
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
guard let urlScheme = url.scheme else { return false }
if urlScheme.hasPrefix("fb") {
return ApplicationDelegate.shared.application(app, open: url, options: options)
}
return true
}
// above for fb sdk nothing
//
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
self.saveContext()
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "LetsGoTogether")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
This below is my View controller code
import UIKit
import Firebase
import FBSDKLoginKit
import FacebookCore
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, LoginButtonDelegate {
#IBOutlet var fbloginbtnview: FBLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
// fb
fbloginbtnview?.delegate = self
fbloginbtnview?.permissions = ["email"]
}
func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {
if let error = error {
print("error took place\(error.localizedDescription)")
return
}
print("Success")
}
func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
print("user signed out")
}
}
You have declared fbloginbtnview as an implicit optional, which is normal but means it is assumed to be valid. References to it will fail if you haven't connected the outlet to an actual button (or to a button of the right type) in interface builder.

How do you use Firebase within a custom class?

I went through the steps to set up Firebase on my app and it tested well. But when I created a custom swift class to make functions to manage the database, it crashes and says "failed to get default firdatabase instance. must call firapp.configure() before using firdatabase". I called configure() in the AppDelegate but it doesn't seem to be passing through to my custom class. Below is the error I get, my part of the AppDelegate where i called FirebaseApp.configure(), and the custom class. Thanks in advance.
DatabaseTestApp[7814:336288] *** Terminating app due to uncaught exception 'FIRAppNotConfigured', reason: 'Failed to get default FIRDatabase instance. Must call FIRApp.configure() before using FIRDatabase.'
import UIKit
import Firebase
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
}
my custom class:
import Foundation
import UIKit
import FirebaseDatabase
class FirebaseClass
{
var ref:DatabaseReference?
init ()
{
ref = Database.database().reference()
}
}
Assuming you are creating some sort of class called FirebaseManager, do the following:
class FirebaseManager {
public static let instance = FirebaseManager()
private init(){
FirebaseApp.configure()
}
}

Am I doing this correctly? Swift 3 xcode loading data from firebase

The way I currently load my data is in the viewWillAppear on their specific view controllers. My question is should I load all the data on the Home/Main View Controller and pass the data that way? Or is the current way Im doing it better?
I know this is subjective, I'm loading ALOT of data.
Structure:
If you do not want the data to persist between app processes (when the app is closed the data is cleared), you can use Global Variables. When it comes to retrieving data, I suggest you to create a function in AppDelegate called retrieveFromFirebase(), containing every piece of code needed to retrieve data in your app, for all the UIViewControllers of your app. Then you should call it inside
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {}
Then, inside your function, you should assign the snapshot's value to the global variable declared earlier.
Example:
This is an example of how to setup AppDelegate.swift for this:
import UIKit
import CoreData
import Firebase
//declaration of the global variable
var username = String()
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
retrieveFromFirebase()
return true
}
func retrieveFromFirebase(){
// get the data from Firebase
let ref = FIRDatabase.database().reference()
ref.child("username").observe(FIRDataEventType.value, with: { snapshot in
username = snapshot.value! as! String
})
}
// other methods from AppDelegate.swift
}
And when you get to the desired ViewController, set your viewDidAppear function to this:
override func viewDidAppear(_ animated: Bool){
super.viewDidAppear(animated)
yourLabel.text = username
}
And you can just use your username anywhere in the current Module.
Hope it helps!

Use of unresolved identifier 'url'

I'm completely new to API's, and am following this tutorial on appcoda
https://www.appcoda.com/dropbox-api-tutorial/
It's been going very smoothly, but I've run into a problem, and given that I'm a novice, I don't have the first clue with how to fix it.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let appKey = "n00nzv68gtxk6c9" // Set your own app key value here.
let appSecret = "itumv0icksr7yj6" // Set your own app secret value here.
let dropboxSession = DBSession(appKey: appKey, appSecret: appSecret, root: kDBRootDropbox)
DBSession.setShared(dropboxSession)
return true
if DBSession.sharedSession().handleOpenURL(url) {
if DBSession.shared().isLinked() {
NotificationCenter.defaultCenter.postNotificationName("didLinkToDropboxAccountNotification", object: nil)
return true
}
}
return false
}
The problem is in the line
if DBSession.sharedSession().handleOpenURL(url) {
where I get the error
Use of unresolved identifier 'url'
What do I need to do?
Per the tutorial, you need to use the correct delegate method within AppDelegate.swift
// handle custom application schemes
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
if DBSession.sharedSession().handleOpenURL(url) {
print("Url defined as \( url)")
}
}