Print DataBase in swift [duplicate] - ios

This question already has answers here:
Where to configure Firebase in my iOS app in the new SwiftUI App life cycle without AppDelegate and SceneDelegate?
(2 answers)
Closed 1 year ago.
I made the front end of an application but now I have to make the back end and therefore print a DB the problem is that I have an error "Failed to get FirebaseApp instance. Please call FirebaseApp.configure() before using Firestore" :
App delegate :
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
DataBase :
struct New: Identifiable {
var id: String = UUID().uuidString
var news: String
}
class NewsViewModel: ObservableObject {
#Published var news = [New]()
private var db = Firestore.firestore()
func fetchDate() {
db.collection("News").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self.news = documents.map { (QueryDocumentSnapshot) -> New in
let data = QueryDocumentSnapshot.data()
let news = data["News"] as? String ?? "ya r"
return New(news: news)
}
}
}
}
Print DB :
NavigationView {
List(viewModel.news) { news in
VStack(alignment: .leading) {
Text(news.news)
}
.navigationTitle("News")
}
}
.onAppear() {
self.viewModel.fetchDate()
}
Thanks for help

Can you add it inside willFinishLaunchingWithOptions
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}

Related

Firebase Dynamic Links on iOS do not work. The Dynamic Link url is always nil

I've created a number of links with a custom URL scheme in Firebase and while I am able to open the app when selecting the link in Notes, the dynamic link is always nil.
Here's the code calling the Dynamic Links api:
public struct FirebaseBridge {
public static func configure() {
FirebaseOptions.defaultOptions()?.deepLinkURLScheme = "mycustomurlscheme"
MyFirebase.configure(crashlyticsIncludeDeviceId: false)
}
public static func setPushMessagingDelegate(_ pushMessagingDelegate: MessagingDelegate) {
Messaging.messaging().delegate = pushMessagingDelegate
}
public static func openDynamicLinkFromURL(_ url: URL) -> Bool {
print(url.absoluteString)
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url) {
self.handleIncomingDynamicLink(dynamicLink)
return true
}
return false
}
public static func handleUniversalLinkFromURL(_ url: URL) -> Bool {
let handled = DynamicLinks.dynamicLinks().handleUniversalLink(url) { (dynamiclLnk, error) in
guard error == nil, let dynamicLink = dynamiclLnk else {
print("error")
return
}
print(dynamicLink)
print(dynamiclLnk?.url ?? "no URL")
FirebaseBridge.handleIncomingDynamicLink(dynamicLink)
}
return handled
}
private static func handleIncomingDynamicLink(_ dynamicLink: DynamicLink) {
guard let url = dynamicLink.url else {
print(dynamicLink)
return
}
print(url.absoluteString)
}
public static func performDiagnostics() {
DynamicLinks.performDiagnostics(completion: { diagnostic, error in
print(diagnostic)
})
}
}
Here is the relevant code in the AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Keep this first at app launch.
FirebaseBridge.configure()
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return FirebaseBridge.openDynamicLinkFromURL(url)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard let url = userActivity.webpageURL else {
return false
}
return FirebaseBridge.handleUniversalLinkFromURL(url)
}
}
Here's the output of the performDiagnostics call:
---- Firebase Dynamic Links diagnostic output start ----
Firebase Dynamic Links framework version 4.0.8
System information: OS iOS, OS version 13.3.1, model iPhone
Current date 2020-06-08 17:35:58 +0000
Device locale en-US (raw en_US), timezone America/Los_Angeles
Specified custom URL scheme is mycustomurlscheme and Info.plist contains such scheme in CFBundleURLTypes key.
AppID Prefix: prefix, Team ID: teamid, AppId Prefix equal to Team ID: YES
performDiagnostic completed successfully! No errors found.
---- Firebase Dynamic Links diagnostic output end ----
Any help would be appreciated!

iOS - Restore app state by coordinators after terminate

Navigation system in my app contains coordinator pattern. when my application starts for the first time, everything works well. But when the app recedes into the background and phone system terminate it and I'm trying to get back to it, app starts for the first time again. So I need to restore my app state if system terminate app in background.
My AppDelegate class
import UIKit
import Swinject
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let container = Container()
private var appCoordinator: AppCoordinator!
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
setupDependecies()
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
appCoordinator = AppCoordinator(window: window!, container: container)
appCoordinator.start()
window?.makeKeyAndVisible()
return true
}
func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool {
return true
}
func application(_ application: UIApplication, shouldRestoreSecureApplicationState coder: NSCoder) -> Bool {
return true
}
}
AppCoordinator class
import Foundation
import UIKit
import Swinject
enum AppChildCoordinator {
case serial
case topic
}
final class AppCoordinator: Coordinator {
private let window: UIWindow
let container: Container
private var childCoordinators = [AppChildCoordinator: Coordinator]()
private let navigationController: UINavigationController
private let plistService: PlistService
init(window: UIWindow, container: Container) {
self.window = window
self.container = container
navigationController = UINavigationController()
self.window.rootViewController = navigationController
plistService = container.resolve(PlistService.self)!
}
func start() {
let isActivated: Bool?
isActivated = plistService.readPlist(namePlist: "Preferences", key: Constans.isActivated) as! Bool?
if isActivated != nil && isActivated! {
showTopic()
} else {
showSerial()
}
}
private func showSerial() {
let serialCoordinator = SerialCoordinator(container: container, navigationController: navigationController)
childCoordinators[.serial] = serialCoordinator
serialCoordinator.delegate = self
serialCoordinator.start()
}
private func showTopic() {
let topicCoordinator = TopicCoordinator(container: container, navigationController: navigationController)
childCoordinators[.topic] = topicCoordinator
topicCoordinator.delegate = self
topicCoordinator.start()
}
}
extension AppCoordinator: SerialCoordinatorDeligate {
func serialCoordinatorDidFinish() {
childCoordinators[.serial] = nil
showTopic()
}
}
extension AppCoordinator: TopicCoordinatorDeligate {
func topicCoordinatorDidFinish() {
childCoordinators[.topic] = nil
}
}
I understand that when my app starts it run Serial or Topic coordinator without restore logic. For example if user go to Topic coordinator, then to Auth coordinator (child of Topic coordinator), then to Home coordinator (child of Auth coordinator), how can I restore Home coordinator after start terminated by system app?

Why Firebase Remote Config doesn't update values?

I'm using Firebase Remote Config, I have some troubles to update values.
My values are updated only if I close and relaunch the app.
But never if my app enters in foreground.
The developer is activated, with no cache delay.
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
let _ = RCFirebaseValues.sharedInstance
}
}
My Firebase Remote Config class:
enum ValueKey: String {
case force_update
}
class RCFirebaseValues {
static let sharedInstance = RCFirebaseValues()
var loadingDoneCallback: (() -> ())?
var fetchComplete: Bool = false
private init() {
loadDefaultValues()
fetchCloudValues()
}
func loadDefaultValues() {
RemoteConfig.remoteConfig().setDefaults(fromPlist: "RemoteConfigDefaults")
}
func fetchCloudValues() {
#if DEBUG
let expirationDuration: TimeInterval = 0
RemoteConfig.remoteConfig().configSettings = RemoteConfigSettings(developerModeEnabled: true)
#else
let expirationDuration: TimeInterval = 3600
#endif
RemoteConfig.remoteConfig().fetch(withExpirationDuration: expirationDuration) {
[weak self] (status, error) in
guard error == nil else {
DLog(message:"Uh-oh. Got an error fetching remote values \(String(describing: error))")
return
}
RemoteConfig.remoteConfig().activateFetched()
self?.fetchComplete = true
self?.loadingDoneCallback?()
}
}
func bool(forKey key: ValueKey) -> Bool {
return RemoteConfig.remoteConfig()[key.rawValue].boolValue
}
func string(forKey key: ValueKey) -> String {
return RemoteConfig.remoteConfig()[key.rawValue].stringValue ?? ""
}
func double(forKey key: ValueKey) -> Double {
if let numberValue = RemoteConfig.remoteConfig()[key.rawValue].numberValue {
return numberValue.doubleValue
} else {
return 0.0
}
}
}
What's wrong?
EDIT after Mosbah's response:
class AppDelegate: UIResponder, UIApplicationDelegate {
var remoteConfig:RCFirebaseValues!
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
self. remoteConfig = RCFirebaseValues.sharedInstance
}
}
Your RCFirebaseValues scope is wrong, it will be nil as soon as you are out of application: didFinishLaunchingWithOptions: so you should keep a strong reference to your object (create a var on AppDelegate).

How can I check UserDefaults after terminate and reopen an app in Xcode (swift)

I archived an object which adopted Codable, and implemented storing the object data when the app enters background, loading them when the app is reopened.
But it doesn't work.
How can I check the UserDefaults' changes after terminate and reopen the simulator?
I made 'Machine' class Codable, and implemented 'MachineStore' class which archives a Machine object.
Saving data:
func saveChanges() {
var data = Data()
do {
data = try encoder.encode(self.machine)
} catch {
NSLog(error.localizedDescription)
}
UserDefaults.standard.set(data, forKey: MachineStore.Key)
}
Loading data:
func loadMachine() {
guard let data = UserDefaults.standard.data(forKey: MachineStore.Key) else { return }
do {
machine = try decoder.decode(VendingMachine.self, from: data)
} catch {
NSLog(error.localizedDescription)
}
}
And I used MachineStore in AppDelegate.
let machineStore: MachineStore = MachineStore()
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
machineStore.loadMachine()
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
machineStore.saveChanges()
}
Encode/Decode your object before. You can use for instance this code below :
extension UserDefaults {
func persist<Value>(_ value: Value, forKey key: String) where Value : Codable {
guard let data = try? PropertyListEncoder().encode(value) else { return }
set(data, forKey: key)
}
func retrieveValue<Value>(forKey key: String) -> Value? where Value : Codable {
return data(forKey: key).flatMap { try? PropertyListDecoder().decode(Value.self, from: $0) }
}
}

Swift 3 '[UIApplicationLaunchOptionsKey : Any]?' is not convertible to '[String : NSString]'

I have a TVOS app that has been converted form Swift 2 to Swift 3 and I am getting the following error. I am unsure how to silence it.
'[UIApplicationLaunchOptionsKey : Any]?' is not convertible to '[String : NSString]'
It is showing up in this piece of code
appControllerContext.launchOptions["BASEURL"] = AppDelegate.TVBaseURL
if let launchOptions = launchOptions as? [String: AnyObject] {
for (kind, value) in launchOptions {
appControllerContext.launchOptions[kind] = value
}
}
ADDED:
/*
Copyright (C) 2015 Hani Hamrouni. All Rights Reserved.
*/
import UIKit
import TVMLKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, TVApplicationControllerDelegate {
// MARK: Properties
var window: UIWindow?
var appController: TVApplicationController?
//change the link to your host url
static let TVBaseURL = "http://google.com"
static let TVBootURL = "\(AppDelegate.TVBaseURL)js/application.js"
// MARK: UIApplication Overrides
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
/*
Create the TVApplicationControllerContext for this application
and set the properties that will be passed to the `App.onLaunch` function
in JavaScript.
*/
let appControllerContext = TVApplicationControllerContext()
/*
The JavaScript URL is used to create the JavaScript context for your
TVMLKit application. Although it is possible to separate your JavaScript
into separate files, to help reduce the launch time of your application
we recommend creating minified and compressed version of this resource.
This will allow for the resource to be retrieved and UI presented to
the user quickly.
*/
if let javaScriptURL = URL(string: AppDelegate.TVBootURL) {
appControllerContext.javaScriptApplicationURL = javaScriptURL
}
appControllerContext.launchOptions["BASEURL"] = AppDelegate.TVBaseURL
if let launchOptions = launchOptions {
for (kind, value) in launchOptions {
appControllerContext.launchOptions[kind.rawValue] = value as AnyObject
}
}
appController = TVApplicationController(context: appControllerContext, window: window, delegate: self)
return true
}
// MARK: TVApplicationControllerDelegate
func appController(_ appController: TVApplicationController, didFinishLaunching options: [String: Any]?) {
print("\(#function) invoked with options: \(options)")
}
func appController(_ appController: TVApplicationController, didFail error: Error) {
print("\(#function) invoked with error: \(error)")
let title = "Error Launching Application"
//error message
let message = error.localizedDescription
let alertController = UIAlertController(title: title, message: message, preferredStyle:.alert )
self.appController?.navigationController.present(alertController, animated: true, completion: { () -> Void in
// ...
})
}
func appController(_ appController: TVApplicationController, didStop options: [String: Any]?) {
print("\(#function) invoked with options: \(options)")
}
}
You'd better work with [UIApplicationLaunchOptionsKey : Any] as it is.
How is this?
if let launchOptions = launchOptions {
for (kind, value) in launchOptions {
appControllerContext.launchOptions[kind.rawValue] = value
}
}
UPDATED
Seems the type of the property launchOptions of TVApplicationControllerContext is [String: Any], so you have no need to cast with as AnyObject.
try this code please and tell me what happen.
appControllerContext.launchOptions["BASEURL"] = AppDelegate.TVBaseURL
if let launchOptions = launchOptions as? [String: Any] {
for (kind, value) in launchOptions {
appControllerContext.launchOptions[kind] = value
}
}

Resources