Custom tableview cell - UIPlacement

Hey All,


I have this UITable with a custom cell. This table gets filled with data from an json file. I want to create a chat like function so the contents are messages between 2 people. To determine who sends what i use an if statement.


I want to Anchor messages send by the current logged in user on the left hand side and messages received on the right hand side of the viewcontroller. Also the messages need to get placed underneath eachother with some spacing.


I have tryed placing the mycell.content2 in a different UITextView. I have added a UIView in the hope that would get me the desired result but up till now nothing has worked.


This is somewhat what i would like to achieve

https://ibb.co/gjv4jtM


How can i achieve this. Is it even possible with an UITableView or do i really need to switch to an UICollectionView?


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var mycell = self.tableChat.dequeueReusableCell(withIdentifier: mycellID) as! ChatCell
let userId: String? = KeychainWrapper.standard.string(forKey: "id")

//if im the one receiving
if mydata[indexPath.row].from != userId {
mycell.chatContent.backgroundColor = orangeBanner
mycell.chatContent.textAlignment = .right
mycell.chatContent.textContainerInset = UIEdgeInsets(top: 10, left: 25, bottom: 10, right: 5)
mycell.chatContent.sizeToFit()
mycell.content2 = mydata[indexPath.row].from
}
//if im the on sending
if mydata[indexPath.row].from == userId{
mycell.chatContent.backgroundColor = grayBanner
mycell.chatContent.textAlignment = .left
mycell.chatContent.sizeToFit()
mycell.chatContent.textContainerInset = UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 25)
mycell.content = mydata[indexPath.row].from
}

return mycell
}


Custom Cell


import Foundation
import UIKit

class ChatCell: UITableViewCell {

    var content: String?
    var content2: String?


    var chatContent : UITextView = {
        var textView = UITextView()

        textView.translatesAutoresizingMaskIntoConstraints  = false
        textView.font = UIFont.boldSystemFont(ofSize: 12)
        textView.heightAnchor.constraint(equalToConstant: 60).isActive = false
        textView.isScrollEnabled = false
        textView.isUserInteractionEnabled = false
        return textView
    }()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?){
        super.init(style: style, reuseIdentifier: reuseIdentifier)

    }
  required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
  
    override func layoutSubviews() {
        super.layoutSubviews()
      
    
        if  let content = content {
            self.addSubview(chatContent)

            chatContent.text = content
            chatContent.leftAnchor.constraint(equalTo: self.lefttAnchor, constant: 10).isActive = true
            chatContent.translatesAutoresizingMaskIntoConstraints = false
    
            chatContent.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            chatContent.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        }
      

 
        if  let content2 = content2 {
            self.addSubview(chatContent)

            chatContent.text = content2
            chatContent.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
            chatContent.translatesAutoresizingMaskIntoConstraints = false
    
            chatContent.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
            chatContent.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        }

    }
}

Accepted Reply

I've looked rapidly.


Why don't you create 2 fields inside the cell: leftMessage and rightMessage.

You position (leading or trailing constraint) on left or right and justify as on left or right

You set their color to grey and orange

You populate depending on emitter / receiver

You hide the field that you do not use

Replies

I've looked rapidly.


Why don't you create 2 fields inside the cell: leftMessage and rightMessage.

You position (leading or trailing constraint) on left or right and justify as on left or right

You set their color to grey and orange

You populate depending on emitter / receiver

You hide the field that you do not use

This isn’t a question about a feature of the Swift language. It would have been better posted in a different forum such as Getting Started or Cocoa Touch.


You’re making a few classic mistakes. In your cellForRowAt... you need to set BOTH content and content2 in all cases. Remember cells can be reused. So one or the other may have data hanging around from last time. You need to explicitly set to nil the one that should be nil. ALL properties on the cell must be set every time.


In your custom cell, you must not add subviews in layoutSubviews. Only layout related tasks should be performed there. It may be called many many times and you’ll be adding new sub views over and over again.


Similarly, you shouldn’t create new constraint objects there either. You should create the text view and the left and right constraints when the cell is created, and keep references to them. Then, when content or content2 is set (I might use didSet { } for this) you would activate whichever one is appropriate and deactivate the other. You might find that you don’t need to override layoutSubviews at all. updateConstraints might be better anyway if doing it in the property setters doesn’t work.


Taking a step back, I would also do all that layout related stuff (background colour, size to fit etc.) in the custom cell class. That’s kind of the whole point of having a custom cell class - so the view controller doesn’t have to know about all the implementation details of the layout within the cell.

Thanks for ur response. I have added mycell.content = nil. Now the output i get is correct. Still unsure how to set the anchors though. When trying to place the anchors in the cellForRowAt (where i also set content and content2) lets the app crash.


How can i place backgroundcolor in the custom cell class while keeping the ability to use multiple colors? I could create multiple textview's i suppose but then the cells just get place next to eachother instead of underneath.

I tryed that but then the messages get the left message and the right message get placed next to eachother instead of underneath.

Hmm sorry with the hiding i almost got the result im looking for some rows get a weird height but what you suggested does seem to work. thankx.