Кэшируйте данные сервера глобально и обновляйте представления - PullRequest
0 голосов
/ 30 мая 2019

Я создаю приложение, которое использует firebase для аутентификации и работы с базой данных. Как только пользователь регистрируется, для него сохраняется запись в базе данных, содержащая некоторую основную информацию, такую ​​как имя, фамилия и т. Д.

Как только пользователь входит в систему со своими учетными данными, я хочу установить глобальную переменную (возможно, userDefaults?), Которая содержит пользовательские данные для этого конкретного пользователя. В противном случае мне нужно получать пользовательские данные каждый раз, когда я хочу заполнить ярлык, например, именем пользователя.

Мне удалось установить userdefaults при входе в систему и использовать эту информацию в UIlables. Но когда я разрешаю пользователям вносить изменения в свои данные, некоторые из которых важны для функционирования приложения, я могу обновить сервер и пользователя по умолчанию, но само приложение не обновляется с правильными данными. Он сохраняет старые данные в (например) UIlables.

Мне бы хотелось получить больше информации о том, как лучше всего управлять такими ситуациями.

При открытии приложения tabBarController устанавливается как rootviewcontroller. При загрузке tabbarcontroller у меня есть следующий код, извлекающий пользовательские данные из firebase и сохраняющий их в userdefaults:

guard let uid = Auth.auth().currentUser?.uid else { return }
            Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
                print(snapshot.value ?? "")


              guard let dictionary = snapshot.value as? [String: Any] else { return }
                let firstname = dictionary["First name"] as? String
                let lastname = dictionary["Last name"] as? String

                print("first name is: " + firstname!)

                UserDefaults.standard.set(firstname, forKey: "userFirstName")

                print(UserDefaults.standard.value(forKey: "userFirstName"))


                self.setupViewControllers()


            }

Затем я продолжаю загрузку всех контроллеров представления во вкладке BarController:

self.setupViewControllers()

В ходе этого процесса метки в этих контроллерах представления заполняются данными пользовательских данных по умолчанию.

Это пример метки, которая заполняется userDefaults, но не обновляется при изменении userdefaults:

    let welcomeLabel: UILabel = {
        let label = UILabel()  
        let attributedText = NSMutableAttributedString(string: "Welcome ")
        attributedText.append(NSAttributedString(string: "\(UserDefaults.standard.string(forKey: "userFirstName")!)"))
        label.attributedText = attributedText
        label.font = UIFont.systemFont(ofSize: 30, weight: .bold)
        return label
    }()

это функция, которую я использую для обновления имени (через текстовое поле, заполненное пользователем):

    @objc func updateName() {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        Database.database().reference().child("users").child(uid).updateChildValues(["First name" : updateNameField.text ?? ""])

        UserDefaults.standard.set(updateNameField.text, forKey: "userFirstName")

        print(UserDefaults.standard.value(forKey: "userFirstName"))
    }

1 Ответ

0 голосов
/ 30 мая 2019

Так что вам придется сначала все организовать. В новом файле определите константы, такие как ниже. Эти константы будут доступны в глобальном масштабе, если только private

Constants.swift

private let storedusername = "usname"
    private let storedName = "uname"
    private let displaypic = "udp"
    private let aboutme = "udesc"

    var myusername : String {
        get {
            return (UserDefaults.standard.string(forKey: storedusername)!)
        } set {
            UserDefaults.standard.set(newValue, forKey: storedusername)
        }
    }

    var myname : String {
        get {
            return (UserDefaults.standard.string(forKey: storedName)!)
        } set {
            UserDefaults.standard.set(newValue, forKey: storedName)
        }
    }

    var myProfileImage : Data {
        get {
            return (UserDefaults.standard.data(forKey: displaypic)!)
        } set {
            UserDefaults.standard.set(newValue, forKey: displaypic)
        }
    }

    var myAboutMe : String? {
        get {
            return (UserDefaults.standard.string(forKey: aboutme)!)
        } set {
            UserDefaults.standard.set(newValue, forKey: aboutme)
        }
    }

Теперь, когда вы захотите сохранить что-либо в UserDefaults в следующий раз, вы просто выполните следующие действия в любом месте базы кода:

myusername = "@CVEIjk"

И чтобы получить его, просто назовите его:

print(myusername)

ВАЖНОЕ ПРИМЕЧАНИЕ -

  1. Всегда не забывайте инициализировать их. Вы можете сделать это, когда пользователь зарегистрируется. Как только они заполнили свои данные и нажали «отправить», просто сохраните их в этих переменных. Это не вызовет ненужного сбоя.

  2. Вам придется сохранять их в каждом месте, где вы выполняете обновления для этих узлов в базе данных.

Теперь, часть освежающих видов. Я использую сценарий, в котором ваш ProfileView.swift имеет вид, и пользователь переходит на EditProfile.swift для обновления содержимого.

Вы инициализируете всех своих наблюдателей в месте, где обновление будет иметь немедленный эффект. Потому что вид сразу после обновления имеет значение. Остальные будут вызваны через геттер aboutme

ProfileView.swift

func openEditView() {

        NotificationCenter.default.addObserver(self, selector: #selector(fetchUserDetails), name: Notification.Name("update"), object: nil)

        //setting this right before the segue will create an observer specifically and exclusively for updates. Hence you don't have to worry about the extra observers.

        perform(segue: With Identifier:)// Goes to the editProfile page
    }

Эта функция будет первоначально вызываться в viewDidLoad (). В это время вам нужно убедиться, что у вас есть все данные, иначе они не будут давать значения. Но если вы храните все по мере регистрации пользователя, вы в безопасности.

@objc func fetchUserDetails() {
        if uid != nil {
            if myname.count > 0 { // This will check if the variable has anything in the memory or not. Dont confuse this with [Array].count
                self.nameLabel = myname
            }
        }
    }

Эта функция также действует методом ab наблюдателя. Поэтому, когда уведомления публикуются, они могут запускаться снова.

Сейчас EditProfile.swift

В блоке, где вы обновляете сервер, сохраните значения, а затем создайте Notification.post и поместите этот метод прямо перед вами dismiss(toViewController:)

   func updateUserCacheData(name: String, username: String, aboutme: String, ProfilePhoto: UIImage? = nil) {
        DispatchQueue.global().async {
            myname = name
            myusername = username
            myAboutMe = aboutme
            if self.newImage != nil {
                myProfileImage = self.newImage!.jpegData(compressionQuality: 1)!
            }
            DispatchQueue.main.async {
                NotificationCenter.default.post(name: .refreshProfileViews, object: nil)
            }
        }
    }

    func updateToServerAndBackToProfileView() {
        self.updateUserCacheData(name: iname!, username: iusername, aboutme: iaboutme!)
        self.dismiss(animated: true, completion: nil)
        }
    }

Пока все возвращается к ProfileView, ваши взгляды будут мгновенно обновляться. Вы можете держать наблюдателя там, где вы просматриваете, который будет отображаться первым после увольнения. Остальные всегда будут получать обновленный контент. Кроме того, не забудьте deinit вашего наблюдателя в ProfileView

//This code is in ProfileView.swift
deinit {
        NotificationCenter.default.removeObserver(self, name: Notification.Name("update"), object: nil)
    }

Кроме того, в случаях, когда содержимое может быть пустым, просто инициализируйте его с пустым содержимым. Например, если пользователь не хочет добавлять aboutme во время регистрации, вы можете просто поставить

`myaboutme = ""`

Это создаст безопасную среду для вас, и вы хорошо настроены.

...