【问题标题】:Why am I getting a nil value when I go to use the value but when I print it it shows up as none nil?为什么我在使用该值时得到一个 nil 值,但当我打印它时它显示为 none nil?
【发布时间】:2019-12-17 18:09:24
【问题描述】:

我正在尝试填充集合视图。当我在字典中使用一个值时,它显示为 nil,但是当我打印它时,它会在它为我提供字符串之前的行。

我之前修复了这个问题,但是当我重新制作我的收藏视图以解决我遇到的另一个错误时,这个错误又回来了。为了解决这个问题,我刚刚删除了 self.users.removeAll() 行。重新添加该行然后删除它这次不起作用。

我在这个函数中遇到了问题:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "userCell", for: indexPath) as! UserCell

    print(user[indexPath.row].imagePath!)

    cell.userImage.sd_setImage(with: URL(string: user[indexPath.row].imagePath!))

    cell.nameLabel.text = user[indexPath.row].username
    cell.userID = user[indexPath.row].userID

    return cell
}

这里是完整的代码:

import UIKit
import Firebase
import SwiftKeychainWrapper
import SwiftUI
import FirebaseUI

class UserViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionview: UICollectionView!

    var user = [User]()

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionview.delegate = self
        collectionview.dataSource = self

        retrieveUsers()
    }

    func retrieveUsers() {
       let ref = Database.database().reference()
       ref.child("users/").observeSingleEvent(of:.value, with: { (snapshot) in
          let users = snapshot.value as! [String : NSDictionary]
          //self.user.removeAll()
          for (_, value) in users {
             if let uid = value["uid"] as? String {
                if uid != Auth.auth().currentUser!.uid {
                   let userToShow = User()
                   if let username = value["username"] as? String, let imagePath = value["urlToImage"] as? String {
                      userToShow.username = username
                      userToShow.imagePath = imagePath
                      userToShow.userID = uid
                      self.user.append(userToShow)
                      print(userToShow)
                   }
                }
             }
          }

          self.collectionview.reloadData()
       })

       ref.removeAllObservers()
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "userCell", for: indexPath) as! UserCell

        print(user[indexPath.row].imagePath!)

        cell.userImage.sd_setImage(with: URL(string: user[indexPath.row].imagePath!))
        cell.nameLabel.text = user[indexPath.row].username
        cell.userID = user[indexPath.row].userID

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return user.count //?? 0
    }

    func checkFollowing(indexPath: IndexPath) {
       let uid = Auth.auth().currentUser!.uid
       let ref = Database.database().reference()

       ref.child("users").child(uid).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
           if let following = snapshot.value as? [String : AnyObject] {
              for (_, value) in following {
                 if value as! String == self.user[indexPath.row].userID {
//                  self.tableview.cellForRow(at: indexPath)?.accessoryType = .checkmark
                 }
              }
           }
       })

       ref.removeAllObservers()

    }

    @IBAction func logOutPressed(_ sender: Any) {
        KeychainWrapper.standard.removeObject(forKey:"uid")

        do {
            try Auth.auth().signOut()
        } catch let signOutError as NSError{
            print("Error signing out: %@", signOutError)
        }
        dismiss(animated: true, completion: nil)
    }
}


extension UIImageView {
    func downloadImage(from imgURL: String!) {
        let url = URLRequest(url: URL(string: imgURL)!)

        let task = URLSession.shared.dataTask(with: url) {  (data, response, error) in
            if error != nil {
                print(error!)
                return
            }

            DispatchQueue.main.async {
                self.image = UIImage(data: data!)
            }
        }

        task.resume()
    }
}

我没有正确填充字典吗?

另外,这里是 User 类:

import UIKit

class User: NSObject {
    var userID: String?
    var username: String?
    var imagePath: String?
}

另外,这是用户字典在调试器中显示的内容:

【问题讨论】:

  • 什么是sd_setImage?如果它是异步的,那就是问题所在。你的代码没有按照你想象的顺序运行。
  • sd_setImage 是设置 ImageView 的函数。为什么 print 语句会打印一些东西,但紧随其后的行不起作用?异步真的那么不稳定吗?在我重新制作 collectionView 之前,同样的代码正在工作,所以我认为这是另外一回事,但我对 Xcode 太陌生,无法理解
  • 因为后面的行并不是真正的后面。这就是异步的意思。
  • 有没有办法确保该行在之后执行?据我了解,在我调用 reloadData() 之前,不应该格式化集合视图。在用户字典中的条目完成之前,我不会调用 reloadData()。如何确保在所有数据都存在之前不会形成单元格?
  • Nick,请学习了解异步数据处理的工作原理。请接受一些建议,例如在主线程上重新加载集合视图并使用非可选属性和初始化程序声明 User。如果他们对您有帮助,请考虑投票并接受答案。

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

如果您遇到此错误,请重新连接到您的集合视图单元

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多