Tableview reuse and imageView show wrong image in swift

512 views Asked by At

I have a chat app, but I face a problem that about cell reuse.
My cell has imageView, and other label.
When I have new message, and I enter the chat view.
My imageView looks something wrong.
The imageView will show me two the same image.
What's wrong about my situation?
Thanks.

Question video link in Youtube

class ChatroomViewController: UIViewController {

    var contents:[Message] = [Message]()
    var tableView:UITableView = UITableView()

    override func viewDidLoad() {
       super.viewDidLoad()

       let msgArray:[Message] = Message.getBy(now)
       contents = msgArray.reversed()

       if contents.count > 0 {
       self.tableView.scrollToRow(at: IndexPath.init(row: (self.contents.count)-1,section: 0), at: .top, animated: true)
       }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard contents.count != 0 else {
           let cell = UITableViewCell()
           return cell
        }
        let content = contents[indexPath.row] as Message

        let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell", for: indexPath) as! ImageTableViewCell

        print("==) Index.row: \(indexPath.row)")

        cell.loadImageMessage(message: content, chatroomId: chatroomId)

        return youVillageImageCell

     }
}

class ImageTableViewCell: UITableViewCell {

weak var user:User?
@IBOutlet weak var ImageView: UIImageView!
@IBOutlet weak var NameLabel: UILabel!
@IBOutlet weak var ChatImageView: MenuImageView!
@IBOutlet weak var DateLabel: UILabel!
override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    ChatImageView.image = nil //Search from stackoverflow, but not working!! 
    ChatImageView.layer.masksToBounds = true 
    ChatImageView.layer.cornerRadius = defaultRadius

}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

override func prepareForReuse() {
    super.prepareForReuse()

    user = nil
    NameLabel.text = nil
    ImageView.image = nil
    ChatImageView.image = nil //Search from stackoverflow, but not working!! 
    DateLabel.text = nil
}

deinit{
    ImageView.removeFromSuperview()
    ChatImageView.removeFromSuperview()

    ImageView = nil
    ChatImageView = nil
    user = nil

    print("==) deinit ImageTableViewCell")
}

func loadImageMessage(message:Message, chatroomId:String) {

    messageImageFromUrl(imageView: youChatImageView, message: message, chatroomId: chatroomId, size: "m")
}
}


func messageImageFromUrl(imageView:UIImageView, message:Message, chatroomId:String, size:String) {

var documentsDirectoryURL:URL

documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("\(chatroomId)/Image/")

let exist = FileManager.default.fileExists(atPath: documentsDirectoryURL.path)

if !exist {

    do {
        try FileManager.default.createDirectory(atPath: documentsDirectoryURL.path, withIntermediateDirectories: true, attributes: nil)
    } catch let error as NSError {
        debug(object: error)
    }
}

var imageUrl:String = message.content

let fileName = imageUrl.md5()
let fileURL = documentsDirectoryURL.appendingPathComponent(fileName)
if let image = UIImage(contentsOfFile: fileURL.path) {
    DispatchQueue.main.async {
        imageView.image = image
    }
    return
}

let urlString = URL(string: imageUrl)
DispatchQueue.global().async {
    let data = try? Data(contentsOf: urlString!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
    if data != nil
    {
        if let image = UIImage(data: data!)
        {
            if !FileManager.default.fileExists(atPath: fileURL.path) {

                var c = [UInt32](repeating: 0, count: 1)
                (data! as NSData).getBytes(&c, length: 1)
                switch (c[0]) {
                case 0xFF:

                    if let jpegData = UIImageJPEGRepresentation(image, 0.5) {

                        do {
                            try jpegData.write(to: fileURL, options: .atomic)
                        } catch {
                            debug(object: error)
                        }
                    }
                case 0x89:

                    if let pngData = UIImagePNGRepresentation(image) {
                        do {
                            try pngData.write(to: fileURL, options: .atomic)
                        } catch {
                            debug(object: error)
                        }
                    }
                case 0x47:
                default:

                }

            } else {
                //print("file already exists")
            }

            DispatchQueue.main.async {
                imageView.image = image
            }
        }
    }
}
}

Question Update

sorry, I print indexPath.row in "cellForRowAt" and It also prints new message indexpathRow again like following message.

==) Index.row: 4
==) Index.row: 2
==) Index.row: 3
==) Index.row: 4
0

There are 0 answers