UItableView显示重复的单元格,我的数据有什么问题?

时间:2017-11-29 18:59:11

标签: ios swift xcode uitableview

enter image description here

目前还不确定该怎么办.....我已经被困了好几天。

我使用的是教程here

我使用了他的代码结构,因为我是初学者,这似乎是最佳实践。重复的单元格也有不准确的时间发送和第一条消息。我真的需要帮助。

这是消息控制器(您在上面看到的屏幕):

import UIKit
import Firebase
class MessagesViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {

@IBOutlet weak var messagesLabelOutlet: UILabel!
@IBOutlet weak var messagesTableView: UITableView!

var newUser : User?
var messageArr = [Message]()
var messageDict = [String: Message]()
override func viewDidLoad() {
    super.viewDidLoad()
    messagesTableView.dataSource = self
    messagesTableView.delegate = self;
    self.messagesTableView.register(UserCell.self, forCellReuseIdentifier: "cellId")
    checkIfUserIsLoggedIn()
    messageArr.removeAll()
    messageDict.removeAll()
    messagesTableView.reloadData()
    observeUserMessages()
    configureTableView()
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return messageArr.count;
}

func configureTableView()
{
    messagesTableView.rowHeight = UITableViewAutomaticDimension;
    messagesTableView.estimatedRowHeight = 120.0;
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 72;
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    self.newUser = User()

    if let chatPartnerId = messageArr[indexPath.row].chatPartnerId(){
        self.newUser?.toId! = chatPartnerId;



    let chatPartnerDataRef = Database.database().reference().child("users").child(chatPartnerId)

    chatPartnerDataRef.observeSingleEvent(of: .value) { (snapshot) in
        guard let dict = snapshot.value as? [String : AnyObject] else{
            return

        }
            self.newUser?.userName = dict["username"] as? String
            self.newUser?.picURL = dict["pic"] as? String
            self.newUser?.score = dict["score"] as? String


        self.performSegue(withIdentifier: "goToChatLogControllerPlzFromMessages", sender: self)

    }
    }

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


    let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! UserCell
    let message = messageArr[indexPath.row]

    cell.textLabel?.font = UIFont(name: "Avenir Book" , size: 19);
    cell.detailTextLabel?.font = UIFont(name: "Avenir Light" , size: 14);

    cell.message = message;



    return cell;
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // do not remove
    if segue.identifier == "goToChatLogControllerPlzFromMessages"{
        print("going to chat log")
    let recieveVC = segue.destination as! ChatLogController

    if let textUser = newUser{
        recieveVC.user = textUser;

    }
    }

}

func checkIfUserIsLoggedIn()
{

    if Auth.auth().currentUser?.uid == nil{
        print("uid is nil")

            performSegue(withIdentifier: "noUserFoundGoingBackToLogin", sender: self);

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

        })
    }
}

func observeUserMessages(){

    guard let uid = Auth.auth().currentUser?.uid else{
        checkIfUserIsLoggedIn()
        return;
    }

    let ref = Database.database().reference().child("user-messages").child(uid)

    ref.observe(.childAdded) { (snapshot) in
        let messageId = snapshot.key
        let messagesRef = Database.database().reference().child("messages").child(messageId)
        messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in

            // no duplicate texts as of here
            if let dict = snapshot.value as? [String : AnyObject]
            {
                let message = Message()
                message.fromId = dict["fromid"] as? String;
                message.text = dict["text"] as? String;
                message.timestamp = dict["timestamp"] as? String;
                message.toId = dict["toid"] as? String;

                self.messageArr.append(message)

                if let toID = message.toId{

                    for m in self.messageArr{
                        if message.toId == m.toId && m.fromId == message.fromId || message.toId == m.fromId && m.fromId == message.toId{
                            self.messageDict[toID] = message;

                        }
                    }


                    self.messageArr = Array(self.messageDict.values)
                    self.messageArr.sort(by: { (message1, message2) -> Bool in

                        let time1 = Int(truncating: (message1.timestamp?.numberValue)!)
                        let time2 = Int(truncating: (message2.timestamp?.numberValue)!)

                        return time1 > time2
                    })


                }



                DispatchQueue.main.async {
                    print(message.text!)
                    self.messagesTableView.reloadData()
                }

            }


        })
    }


}

}

我已将错误缩小到此方法:

func observeUserMessages(){

    guard let uid = Auth.auth().currentUser?.uid else{
        checkIfUserIsLoggedIn()
        return;
    }

    let ref = Database.database().reference().child("user-messages").child(uid)

    ref.observe(.childAdded) { (snapshot) in
        let messageId = snapshot.key
        let messagesRef = Database.database().reference().child("messages").child(messageId)
        messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in

            // no duplicate texts as of here
            if let dict = snapshot.value as? [String : AnyObject]
            {
                let message = Message()
                message.fromId = dict["fromid"] as? String;
                message.text = dict["text"] as? String;
                message.timestamp = dict["timestamp"] as? String;
                message.toId = dict["toid"] as? String;

                self.messageArr.append(message)

                if let toID = message.toId{

                    for m in self.messageArr{
                        if message.toId == m.toId && m.fromId == message.fromId || message.toId == m.fromId && m.fromId == message.toId{
                            self.messageDict[toID] = message;

                        }
                    }


                    self.messageArr = Array(self.messageDict.values)
                    self.messageArr.sort(by: { (message1, message2) -> Bool in

                        let time1 = Int(truncating: (message1.timestamp?.numberValue)!)
                        let time2 = Int(truncating: (message2.timestamp?.numberValue)!)

                        return time1 > time2
                    })


                }



                DispatchQueue.main.async {
                    print(message.text!)
                    self.messagesTableView.reloadData()
                }

            }


        })
    }


}

我发现使用这个for循环,我要么加载所有用户,要么重复。

 for m in self.messageArr{
                        if message.toId == m.toId && m.fromId == 
message.fromId || message.toId == m.fromId && m.fromId == message.toId{
                            self.messageDict[toID] = message;

                        }
                    }

感谢所有想要帮助的人。

更新

我在4天后解决了这个问题。解决方案是在数据中,我正在加载具有toID和fromID相同的数据。谢谢大家的帮助

2 个答案:

答案 0 :(得分:0)

单元格被重用,这意味着它们保留了以前的UI信息。在您的CellForRowAt方法中,您需要显式设置图像,人名,时间戳等。

答案 1 :(得分:0)

可能是因为从firebase获取快照时始终向数组附加相同的值 尝试检查数组是否有重复项 为了防止单元格中的相同图像,只需将图像设置为nil,然后提供所需的图像或提供图像占位符,因为单元格总是被重用