代码之家  ›  专栏  ›  技术社区  ›  Chandler Long

Swift 4:UITableViewCell在初始加载时不会显示数据,但会在第二次加载时加载

  •  0
  • Chandler Long  · 技术社区  · 6 年前

    我在申请中遇到了一个非常有趣的问题。在查看用户配置文件页面时,我的tableview中的数据被拉入并打印到控制台中,但问题是我的信息不会加载到我的tablecell中。

    如果我离开当前选项卡,然后返回配置文件页面,那么我的数据将被加载。我正在使用firebase来获取我的信息。

    我希望数据在第一次查看页面时就在那里。

    ProfileViewController

        var cellId = "cell"
        var userGames = [Game]()
        var userCurrentGames = [Any]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            tableView.delegate = self
            tableView.dataSource = self
    
            tableView.register(ProfileGameCell.self, forCellReuseIdentifier: cellId)
    
        //I CALL MY FUNCTIONS UPON FIRST LOAD
            getCurrentUser()
            getUsersGames()
    
            }
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
        //I CALL FUCTIONS EVERY TIME THE VIEW LOADS INCASE DATA CHANGES
            getCurrentUser()
            getUsersInformation()
            getUsersGames()
    
        }
    
        func getUsersGames() {
            let ref = Database.database().reference()
            let current = getCurrentUser()
    
    //I FIND ALL THE GAMES IN THE USERS REF AND APPEND THEIR KEY TO THE ARRAY
                ref.child("users").child(current).child("user games").observe(.value, with: {(snapshot) in
                    if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
                        self.userCurrentGames = []
                        for snap in snapshot {
                            let gameKey = snap.key
    
                            print("SNAPSHOT DATAAA: \(gameKey)")
                            self.userCurrentGames.append(gameKey)
                        }
                    }
                })
                displayUsersGames()
        }
    
    func displayUsersGames() {
        let ref = Database.database().reference()
        self.userGames = []
    //I FIND ALL THE GAMES AND APPEND THEM TO THE ACTUAL GAME ARRAY
        for i in userCurrentGames {
            ref.child("games").child("\(i)").observeSingleEvent(of: .value, with: { (gameSnap) in
                if let gameDict = gameSnap.value as? Dictionary<String, AnyObject> {
                    let key = gameSnap.key
                    let game = Game(postKey: key, gameData: gameDict)
                    self.userGames.append(game)
    
                    self.tableView.reloadData()
                }
            })
        }
    }
    

    表视图功能

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let game = userGames[indexPath.row]
        if let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? ProfileGameCell {
            cell.adminButton.tag = indexPath.row
            cell.configureUserGameCell(game: game)
            return cell
        } else {
            return ProfileGameCell()
        }
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return userGames.count
    }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   vadian    6 年前

    问题很明显:

    observe 异步工作稍后返回结果,因此 userCurrentGames 为空时 displayUsersGames() 被调用。

    解决办法是搬家 displayUsersGames() 进入完成区块

    ...   
    ref.child("users").child(current).child("user games").observe(.value, with: {(snapshot) in
            if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
                self.userCurrentGames = []
                for snap in snapshot {
                    let gameKey = snap.key
    
                    print("SNAPSHOT DATAAA: \(gameKey)")
                    self.userCurrentGames.append(gameKey)
                }
                self.displayUsersGames()
            }
        })
    

    注:

    强制向下投射单元格

    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! ProfileGameCell
    

    代码不能崩溃。如果它这样做了,就会暴露出一个设计错误。