получить информацию из Firebase и установить в качестве изображения и метки в UICollectionView - PullRequest
0 голосов
/ 10 февраля 2019

Я пытаюсь получить некоторые данные, хранящиеся в базе данных firebase, и разрешить отображение этой информации в представлении коллекции.Например, profileImageUrl, метка имени и метка электронной почты.

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

let profileImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.image = UIImage(named: "users")
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    return imageView
}()
let nameLabel: UILabel = {
 let label = UILabel()
    label.text = "User's Name"
    label.font = UIFont.boldSystemFont(ofSize: 18)
    label.textColor = GREEN_Theme
    return label
}()
let uidLabel: UILabel = {
    let label = UILabel()
    label.text = "User's uid"
    label.font = UIFont.boldSystemFont(ofSize: 16)
    label.textColor = GREEN_Theme
    return label
}()
let emailLabel: UILabel = {
    let label = UILabel()
    label.text = "User's email"
    label.font = UIFont.boldSystemFont(ofSize: 16)
    label.textColor = GREEN_Theme
    return label
}()
override init(frame: CGRect) {
    super.init(frame: frame)

    setupView()
}

func setupView() {
if Auth.auth().currentUser != nil {
    guard let uid = Auth.auth().currentUser?.uid else {
        return }
    Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String : Any] else {
            return }
       let user = CurrentUser(uid: uid, dictionary: dictionary)
        self.uidLabel.text = uid
        self.nameLabel.text = user.name
        self.emailLabel.text = user.email
       self.profileImageView.loadImageUsingCacheWithUrlString(user.profileImageUrl)
    }, withCancel: { (err) in
        print("attempting to load information")
      })  
       self.addSubview(profileImageView)
       self.addSubview(nameLabel)
       self.addSubview(emailLabel)
       self.addSubview(uidLabel)
     profileImageView.anchors(top: topAnchor, topPad: 125, bottom: bottomAnchor, bottomPad: 75, left: leftAnchor, leftPad: 20, right: rightAnchor, rightPad: 250, height: 20, width: 20)
    nameLabel.anchors(top: profileImageView.bottomAnchor, topPad: -50, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 0, height: 20, width: 20)
    emailLabel.anchors(top: nameLabel.bottomAnchor, topPad: -80, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 125, height: 20, width: 20)
    uidLabel.anchors(top: emailLabel.bottomAnchor, topPad: -40, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 0, height: 20, width: 20)
    profileImageView.layer.zPosition = 10
    nameLabel.layer.zPosition = 10
    emailLabel.layer.zPosition = 10
    profileImageView.layer.borderWidth = 2.0
    profileImageView.layer.cornerRadius = 50
    profileImageView.layer.borderWidth = 2.0
    profileImageView.layer.borderColor = UIColor.white.cgColor
    profileImageView.layer.masksToBounds = true

 }
}

Я был бы очень признателен, если бы кто-то мог помочь мне критиковать то, что у меня есть, а также показать, как будет выглядеть правильная реализация.Любая помощь будет принята с благодарностью

1 Ответ

0 голосов
/ 10 февраля 2019

Есть несколько вещей, которые не верны.

  1. ваша ячейка не должна отвечать за загрузку или выполнение каких-либо сетевых вызовов, оставьте это для viewController или, что еще лучше, отдельным обработчиком для всех сетевых вызовов.
  2. Firebase является асинхронным, поэтому к моменту загрузки ваших данных все представления уже были настроены и отображены, поэтому вы видите только заполнители.
  3. У вас много избыточного кода для проверки дополнительных функций, это не является большой проблемой, но в этом нет необходимости.

Вы должны подумать об изменении всего этого кода и разделенииразные задачи для разных обработчиков.Например, вы можете создать отдельный класс, который контролирует все вызовы Firebase и возвращает значения с блоками завершения, из viewController или самого collectionView попросите сетевой обработчик предоставить вам необходимые данные, передать эти данные в ячейкуи пусть ячейка отображает данные, ячейка должна только отображать данные, а не загружать их или запрашивать сетевые запросы.Я не могу написать полный пример для вас, но я думаю, что если вы зайдете в Google, вы найдете много очень хороших примеров и учебных пособий.

В любом случае, просто для начала, чтобы вы могли взглянуть на ошибки, которые у вас есть в коде, вот быстрое исправление.Даже если это работает, не принимайте как должное, что все исправлено.Вы должны действительно реорганизовать весь код и разделить различные задачи.Надеюсь, это поможет, по крайней мере, решить проблему отображения загруженных данных в ячейке.

let profileImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.image = UIImage(named: "users")
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    return imageView
}()
let nameLabel: UILabel = {
    let label = UILabel()
    label.text = "User's Name"
    label.font = UIFont.boldSystemFont(ofSize: 18)
    label.textColor = GREEN_Theme
    return label
}()
let uidLabel: UILabel = {
    let label = UILabel()
    label.text = "User's uid"
    label.font = UIFont.boldSystemFont(ofSize: 16)
    label.textColor = GREEN_Theme
    return label
}()
let emailLabel: UILabel = {
    let label = UILabel()
    label.text = "User's email"
    label.font = UIFont.boldSystemFont(ofSize: 16)
    label.textColor = GREEN_Theme
    return label
}()


// Here you add a variable that is observed for SET, once a set happens bind() will be called and the views will be updated.
var currentUser : CurrentUser? {
    didSet {
        self.bind()
    }
}

override init(frame: CGRect) {
    super.init(frame: frame)
    //...
}


// setupView() should only add the UI appearance, and in this case it is calling firebase and setting currentUser, but it should not do that. This is what you have to refactor.
func setupView() {
    self.addSubview(profileImageView)
    self.addSubview(nameLabel)
    self.addSubview(emailLabel)
    self.addSubview(uidLabel)
    profileImageView.anchors(top: topAnchor, topPad: 125, bottom: bottomAnchor, bottomPad: 75, left: leftAnchor, leftPad: 20, right: rightAnchor, rightPad: 250, height: 20, width: 20)
    nameLabel.anchors(top: profileImageView.bottomAnchor, topPad: -50, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 0, height: 20, width: 20)
    emailLabel.anchors(top: nameLabel.bottomAnchor, topPad: -80, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 125, height: 20, width: 20)
    uidLabel.anchors(top: emailLabel.bottomAnchor, topPad: -40, bottom: bottomAnchor, bottomPad: 0, left: profileImageView.leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 0, height: 20, width: 20)
    profileImageView.layer.zPosition = 10
    nameLabel.layer.zPosition = 10
    emailLabel.layer.zPosition = 10
    profileImageView.layer.borderWidth = 2.0
    profileImageView.layer.cornerRadius = 50
    profileImageView.layer.borderWidth = 2.0
    profileImageView.layer.borderColor = UIColor.white.cgColor
    profileImageView.layer.masksToBounds = true

    guard let user = Auth.auth().currentUser else { return }
    let uid = user.uid
    let reference = Database.database().reference().child("users").child(uid)
    reference.observeSingleEvent(of: .value, with: { (snapshot) in
        guard let dictionary = snapshot.value as? [String : Any] else { return }
        self.currentUser = CurrentUser(uid: uid, dictionary: dictionary)
    }, withCancel: { (err) in
        print("attempting to load information")
    })
}

// This is the method that updates the cell views.
func bind() {
    self.uidLabel.text = currentUser.uid
    self.nameLabel.text = currentUser.name
    self.emailLabel.text = currentUser.email
    self.profileImageView.loadImageUsingCacheWithUrlString(currentUser.profileImageUrl)
}
...