简体   繁体   English

iOS swift 应用程序从 firestore 读取数据,数据显示在模拟器上但不在物理设备中

[英]iOS swift application read data from firestore, data shown on simulator but not in physical device

My application read the data correctly and all things work as needed but when I run it on my iphone the data is not shown like it is empty or null, I checked the code try to figure out why but I did not find out the problem.我的应用程序正确读取数据并且所有事情都按需要工作,但是当我在我的 iPhone 上运行它时,数据没有显示,就像它是空的或 null,我检查了代码试图找出原因但我没有发现问题。 and when I read the data directly in " FirstScreenViewController" View Controller the data is appear so I do know exactly where is the problem any help please My code:当我直接在“FirstScreenViewController”View Controller 中读取数据时,数据出现了,所以我确实知道问题出在哪里,请提供任何帮助我的代码:

//
//  DataManager.swift
//  Aqra3
//
//  Created by Mahmoud Abdelaziz on 14/01/2023.
//


import UIKit
import FirebaseFirestore

class DataManager {
    static let shared = DataManager()
    var delegate: DataManagerDelegate?

    //var dataCache = [String: Any]() // for screen 1 [0] is the title
    let currentDateTime = Date()
    var db: Firestore!
    var db2: Firestore!
    var db3: Firestore!

    //var db4: Firestore!
    //var dailyAdvice = String()
    var screenOneBody = String()
    var screenOneTitle = String()
    var screenTwoBody = String()
    var screenTwoTitle = String()
    var screenThreeBody = String()
    var screenThreeTitle = String()
    
    //private init() {}

    func fetchDataFromFirestore(date: String) {
        let settings = FirestoreSettings()
        Firestore.firestore().settings = settings
        db = Firestore.firestore()
        db2 = Firestore.firestore()
        db3 = Firestore.firestore()
        //db4 = Firestore.firestore()
        
        //let topicDay = String(self.currentDateTime.formatted(date: .abbreviated, time: .omitted))// exp Jan 3, 2023

        let screenOne = db.collection("Screen1").document(date)
        screenOne.getDocument{ (document, error) in
            if let document = document, document.exists {
                self.screenOneBody = document.get("Body")! as! String
                self.screenOneTitle = document.get("Title")! as! String
                print("Screen One Body: \(self.screenOneBody) \n")
                print("Screen One Title: \(self.screenOneTitle) \n")
                print("Data: \(date) \n")
               // DispatchQueue.main.async {
               //     self.delegate?.dataDidUpdate()
               // }
                let screenTwo = self.db2.collection("Screen2").document(date)
                screenTwo.getDocument{ (document, error) in
                    if let document = document, document.exists {
                        self.screenTwoBody = document.get("Body")! as! String
                        self.screenTwoTitle = document.get("Title")! as! String
                        print("Screen Two Body: \(self.screenTwoBody) \n")
                        print("Screen Two Title: \(self.screenTwoTitle) \n")
                        print("Data: \(date) \n")
                        
                        let screenThree = self.db3.collection("Screen3").document(date)
                        screenThree.getDocument { (document, error) in
                            if let document = document, document.exists {
                                self.screenThreeBody = document.get("Body")! as! String
                                self.screenThreeTitle = document.get("Title")! as! String
                                print("Screen Three Body: \(self.screenThreeBody) \n")
                                print("Screen Three Title: \(self.screenThreeTitle) \n")
                                print("Data: \(date) \n")
                            } else {
                                        print("Document does not exist")
                                        print("Data: \(date)")
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

protocol DataManagerDelegate {
    func fetchDataFromFirestore(date: String)
    func dataDidUpdate()

}

//
//  FirstScreenViewController.swift
//  Aqra3
//
//  Created by Mahmoud Abdelaziz on 01/01/2023.
//

import UIKit
import SwiftUI
import FirebaseFirestore

class FirstScreenViewController: UIViewController, DataManagerDelegate {
    func fetchDataFromFirestore(date: String) {
        DataManager.shared.fetchDataFromFirestore(date: date)
        changeTheBody()
        DataManager.shared.delegate?.dataDidUpdate()
        
    }
    
    //var newDateFromMenu = SideMenuViewController()
    var db: Firestore!
    let currentDateTime = Date()
    let refreshControl = UIRefreshControl()
    var refreshTimer = Timer()
    
    @IBOutlet weak var FirstScreenTextView: UITextView!
    @IBOutlet weak var firstScreenTitle: UITextView!
    

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.hidesBackButton = true // hide the back button
        let settings = FirestoreSettings()
        Firestore.firestore().settings = settings
        db = Firestore.firestore()
        //self.navigationController!.navigationBar.tintColor = UIColor.red // this if you want to cahnge the navigationBar color without change the global tint color

        //DataManager.shared.fetchDataFromFirestore()
        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))

        swipeLeft.direction = .right
        self.view.addGestureRecognizer(swipeLeft)
        DataManager.shared.delegate = self

        //let topicDay = String(self.currentDateTime.formatted(date: .abbreviated, time: .omitted))// exp Jan 3, 2023
        //DataManager.shared.fetchDataFromFirestore(date: topicDay)
        changeTheBody()
        
        refreshTimer = Timer.scheduledTimer(timeInterval: 0.0, target: self, selector: #selector(changeTheBody), userInfo: nil, repeats: true)
    

    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        refreshTimer.invalidate()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        refreshTimer = Timer.scheduledTimer(timeInterval: 60.0, target: self, selector: #selector(changeTheBody), userInfo: nil, repeats: true)
    }

    
    @objc func changeTheBody() {
        FirstScreenTextView.text =  "\(DataManager.shared.screenOneBody)"
        //FirstScreenTextView.semanticContentAttribute = .forceRightToLeft
        let style = NSMutableParagraphStyle()
        style.lineSpacing = 10  // adjust line spacing as needed
        style.baseWritingDirection = .rightToLeft
        style.alignment = .justified
        let attributes = [    NSAttributedString.Key.paragraphStyle: style]
        FirstScreenTextView.attributedText = NSAttributedString(string: FirstScreenTextView.text, attributes: attributes)
        FirstScreenTextView.font = UIFont.systemFont(ofSize: 20)
        FirstScreenTextView.textColor = UIColor.white
        firstScreenTitle.textColor = UIColor.white
        firstScreenTitle.text =  "\(DataManager.shared.screenOneTitle)"

        refreshControl.endRefreshing()

    }
    @objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
        if gesture.direction == UISwipeGestureRecognizer.Direction.right {
            performSegue(withIdentifier: "fromFirstScreenToMainScreen", sender: self)
        }
    }
    
   /* override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToResult" {
            let destinationVC = segue.destination as! SideMenuViewController
 
        }
    }*/
    func dataDidUpdate() {
        changeTheBody()
    }
}

//
//  AppDelegate.swift
//  AQRA3
//
//  Created by Mahmoud Abdelaziz on 01/01/2023.
//

import UIKit
import FirebaseCore
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    let currentDateTime = Date()



    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        let topicDay = String(self.currentDateTime.formatted(date: .abbreviated, time: .omitted))// exp Jan 3, 2023
        FirebaseApp.configure()
        DataManager.shared.fetchDataFromFirestore(date: topicDay)
        return true
    }

    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }


}

I think I know what is happening here.我想我知道这里发生了什么。

When you read the data in your AppDelegate , it gets read, and the delegate callback ( self.delegate?.dataDidUpdate() ) in the DataManager occurs before you set your FirstScreenViewController view controller as the DataManager 's delegate (on the line DataManager.shared.delegate = self ).当您读取AppDelegate中的数据时,它会被读取,并且DataManager中的委托回调( self.delegate?.dataDidUpdate() )发生在您将FirstScreenViewController视图 controller 设置为DataManager的委托(在DataManager.shared.delegate = self )。 At this point the DataManager 's delegate is nil , so you do not receive the callback in your view controller.此时DataManager的委托为nil ,因此您不会在视图 controller 中收到回调。

The correct way to ensure that you always get the delegate callback would be that you set the DataManager 's delegate before you execute the fetchDataFromFirestore(date: String) call.确保始终获得委托回调的正确方法是在执行fetchDataFromFirestore(date: String)调用之前设置DataManagerdelegate

If this helps you, please consider marking this as the answer.如果这对您有帮助,请考虑将其标记为答案。

I know the problem The data is saved in the firestore with the date in this format Jan 10, 2023 Jan 24, 2023 and so on when get the date i was test getting it with the simulator and the format was the same MMM DD, YYYY, but when turn on the physical device the format was DD MMM, YYYY so I add a code to force the format to be MMM DD, YYYY我知道这个问题数据保存在 firestore 中,日期格式为 2023 年 1 月 10 日 2023 年 1 月 24 日,依此类推,当获取日期时,我正在使用模拟器测试它,格式相同 MMM DD, YYYY , 但是当打开物理设备时格式是 DD MMM, YYYY 所以我添加了一个代码来强制格式是 MMM DD, YYYY

let topicDay = String(self.currentDateTime.formatted(date: .abbreviated, time: .omitted) )// exp Jan 3, 2023
let dateString = topicDay
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"

let date = dateFormatter.date(from: dateString)

dateFormatter.dateFormat = "MMM dd, yyyy"
let newDateString = dateFormatter.string(from: date!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM