Не удается передать данные в пользовательский интерфейс — Swift

#swift #xcode #object #parsing

#swift #xcode #объект #синтаксический анализ

Вопрос:

Добрый день, я пытаюсь передать данные в пользовательский интерфейс моего профиля.

Это мой класс Customer:

 class Customer {
    // Creating a customer
    let name: String
    let surname: String
    let contactNo: String
    let email: String
   
    init(name: String,surname: String,contactNo: String,email: String) {
        
        self.name = name
        self.surname = surname
        self.contactNo = contactNo
        self.email = email
    }
}
  

Это мой код, с помощью которого я пытаюсь проанализировать данные из Firestore для отображения сведений о клиентах:

     class ProfileCus: UIViewController {
    
        // Labels to display data
        @IBOutlet weak var nameLabel: UILabel!
        @IBOutlet weak var surnameLabel: UILabel!
        @IBOutlet weak var emailLabel: UILabel!
        @IBOutlet weak var contactLabel: UILabel!
        
        // Reference to customer collection in Firestore
        private var  customerRefCollection: CollectionReference!
        
        // Customer Object
        private var customer: Customer?
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            
            customerRefCollection = Firestore.firestore().collection("customers")
            
            nameLabel.text = customer?.name
            surnameLabel.text = customer?.surname
            emailLabel.text = customer?.email
            contactLabel.text = customer?.contactNo
            
        }
        
// This function notifies the view controller that the view is about to load so it is best to acquire the data in here before the view loads so that it will be ready to display.

        override func viewWillAppear(_ animated: Bool) {
            // Get the current user ID
            let userID = Auth.auth().currentUser?.uid
            // Locate the user information on Firestore
            customerRefCollection.document(userID!).getDocument { (snapshot, error) in
                if let err = error {
                    debugPrint("Error fetching documents: (err)")
                }
                else {
                    // Ensure that if there's nothing in the document that the function returns
                    guard let snap = snapshot else {return}
                    // Parse the data to the customer model
                    let data = snap.data()
                    
                    let name = data?["name"] as? String ?? ""
                    let surname = data?["surname"] as?  String ?? ""
                    let email = data?["email"] as? String ?? ""
                    let contact = data?["contact no"] as? String ?? ""
                    // Create the customer and pass it to the global variable
                    let cus = Customer(name: name, surname: surname, contactNo: contact, email: email)
                    self.customer = cus
                }
            }
        }
    }
  

Все на стороне Firestore работает нормально, и я могу читать / извлекать данные, но я изо всех сил пытаюсь передать данные в свой пользовательский интерфейс через мой класс Customer. При использовании инструкций печати кажется, что объект customer равен нулю.

Выводите после запуска кода

Комментарии:

1. self.customer = cus Вызывается? Если да, позвольте мне спросить вас вот о чем: nameLabel.text = customer?.name вызывается ДО или после self.customer = cus ? Вам не хватает концепции асинхронности и того факта, что viewWillAppear() следует вызывать после viewDidLoad() ?

2. Подобный код customer?.name говорит, что вам все равно, customer равно nil или нет. Я предлагаю не использовать его, если это не то, что вы действительно имеете в виду. Вместо этого протестируйте значение и, по крайней мере, распечатайте сообщение, чтобы вы знали, что происходит.

3. Larme — Возможно, я совершенно ошибаюсь, но я предположил, что viewWillAppear запускается до загрузки представления, поэтому я подумал, что будет лучше всего получить данные там и подготовить их до загрузки экрана, но, очевидно, мое предположение неверно. Вы предлагаете мне создать новую функцию и поместить все это туда?

4. Филипп Миллс — У меня возникла ошибка, в которой говорилось, что у класса нет инициализаторов, поэтому я погуглил использование кода, подобного customer?.name . Я изо всех сил пытался выяснить, как инициировать частных клиентов var вверху. у вас есть предложения о том, как я могу это сделать?

5. почему бы не сделать Customer как Struct ?

Ответ №1:

 func getDataFromFirebase(completion:@escaping() -> ()){



let userID = Auth.auth().currentUser?.uid
            // Locate the user information on Firestore
            customerRefCollection.document(userID!).getDocument { (snapshot, error) in
                if let err = error {
                    debugPrint("Error fetching documents: (err)")
                }
                else {
                    // Ensure that if there's nothing in the document that the function returns
                guard let snap = snapshot else {return}
                // Parse the data to the customer model
                let data = snap.data()
                
                let name = data?["name"] as? String ?? ""
                let surname = data?["surname"] as?  String ?? ""
                let email = data?["email"] as? String ?? ""
                let contact = data?["contact no"] as? String ?? ""
                // Create the customer and pass it to the global variable
                let cus = Customer(name: name, surname: surname, contactNo: contact, email: email)
                self.customer = cus
            }
completion()
        }
    }


getDataFromFirebase{
customerRefCollection = Firestore.firestore().collection("customers")
        
        nameLabel.text = customer?.name
        surnameLabel.text = customer?.surname
        emailLabel.text = customer?.email
        contactLabel.text = customer?.contactNo
  

}

Итак, что вы в основном делаете здесь, вы сначала получаете данные из firebase и только после того, как эта работа будет выполнена, следовательно, в блоке завершения вы будете настраивать свои данные для просмотра. Вы можете вызвать метод просто в viewDidLoad.

Комментарии:

1. Во-первых, огромное вам спасибо! Я искренне благодарен. Могу ли я попросить вас, пожалуйста, проверить синтаксис для меня, потому что после добавления его в мой проект из-за нескольких ошибок, и это первый раз, когда я имею дело с завершением (), поэтому я не уверен, куда все должно идти. Блок внутри 2-го getDataFromFirebase{block} внизу, он должен быть там?

2. Пожалуйста, помогите с этим?

3. Определите GetDataFromFirebase в любом месте контроллера представления. И вызовите функцию в viewDidLoad, и блок, который вы имели в виду, — это то, где происходит обработка. Блок внутри 2-го getDataFromFirebase выполняется только после получения данных. Получение данных с сервера часто является асинхронной задачей (обычно это происходит в фоновом режиме). Итак, после завершения вы просто получаете уведомление, хорошо, сэр, он получил ваши данные, и внутри завершения вы в основном сообщаете об этом, вам не нужно говорить мне, но делайте то, что я сказал. Итак, он смотрит, есть ли какой-либо обработчик завершения, и выполняет задачу аналогичным образом.