Reputation: 277
I am creating a messaging page in my app and I am having some serious trouble. When the page first loads it looks fine but when you start to scroll down everything gets all messed up. New cells do not load and then when I scroll back up most cells are gone except for normally 1 that shows up and it is in the wrong place.
There is some Async action going on. When the message is sent it sends to the server and then when it returns I reload the data and scroll to that newly entered message at the bottom. This is very buggy as well. Most of the time when sending the message the new cell does not show up. Then after sending 1 or 2 more then will all show up.
Here is my ViewController that is also my Data source and Delegate
import UIKit
class MessageDetailController: UIViewController,UITableViewDataSource,UITableViewDelegate, UITextFieldDelegate {
@IBOutlet weak var lblMessageText: UITextField!
@IBOutlet weak var sendViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var messagesTable: UITableView!
@IBOutlet weak var sendMsgView: UIView!
@IBOutlet weak var sendMessageView: UIView!
var messageDetailArray = [Message]()
override func viewDidLoad() {
super.viewDidLoad()
self.lblMessageText.delegate = self
self.view.bringSubviewToFront(self.sendMessageView)
self.messagesTable.separatorStyle = UITableViewCellSeparatorStyle.None
self.messagesTable.dataSource = self
self.messagesTable.delegate = self
self.messagesTable.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messageDetailArray.count
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
_ = MessageService().sendMessage("James", message: lblMessageText.text!, callback: loadMessages)
lblMessageText.text = ""
return true
}
func loadMessages(jsonData:NSArray){
dispatch_async(dispatch_get_main_queue(),{
var messages = [Message]()
for messageTest in jsonData {
if let message = messageTest as? NSDictionary {
messages.append(Message(messageType:Message.QA.A, from:message["user_display_label"] as! String, messageText:message["message"] as! String, timeSent:NSDate()))
}
}
self.messageDetailArray = messages;
self.messagesTable.reloadData()
self.messagesTable.scrollToRowAtIndexPath(NSIndexPath(forRow: self.messageDetailArray.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
})
}
@IBAction func endedEditing(sender: AnyObject) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.2, animations: {
self.sendViewHeightConstraint.constant = 40
self.view.layoutIfNeeded()
}, completion: nil)
}
@IBAction func startedEditing(sender: AnyObject) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.2, animations: {
self.sendViewHeightConstraint.constant = 295
self.view.layoutIfNeeded()
}, completion: nil)
}
@IBAction func sendMessage(sender: AnyObject) {
_ = MessageService().sendMessage("James", message: lblMessageText.text!, callback: loadMessages)
lblMessageText.text = ""
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let thisMsg = messageDetailArray[indexPath.row]
let cell: MessageDetailATableViewCell = tableView.dequeueReusableCellWithIdentifier("messageCenterA", forIndexPath: indexPath) as! MessageDetailATableViewCell
cell.msgLabel?.text = thisMsg.messageText;
cell.msgLabel.sizeToFit()
cell.msgLabel.numberOfLines = 0
cell.frame = CGRectMake(0,
0,
self.view.bounds.width,
cell.frame.size.height);
let myInsets = UIEdgeInsetsMake(7, 8, 7, 8)
let bubbleImage = UIImage(named: "balloon_read_right")?.resizableImageWithCapInsets(myInsets)
let bubbleImageView = UIImageView(image: bubbleImage)
bubbleImageView.frame = CGRectMake(0, 0, cell.bubbleView.bounds.width, cell.bubbleView.bounds.height)
cell.bubbleView.addSubview(bubbleImageView)
cell.bubbleView.bringSubviewToFront(cell.msgLabel)
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let messageSize:CGSize = PTSMessagingCell.messageSize(messageDetailArray[indexPath.row].messageText)
return messageSize.height + 2 * PTSMessagingCell.textMarginVertical() + 40
}
}
If you read through that you will notice that I use this class so I will include it for you. It is just the tablecell and does not do much.
import UIKit
class MessageDetailATableViewCell: UITableViewCell {
@IBOutlet weak var bubbleView: UIView!
@IBOutlet weak var msgImageView: UIImageView!
@IBOutlet weak var msgLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I have messed around with this code a lot trying to get it to work and I cont find anyone else who has the same bug. Any help would be greatly appreciated!
Thanks!!
Upvotes: 0
Views: 75
Reputation: 27620
The problem is caused by the fact that you set the frame
of your cells. You set the origin of all cells to (0,0). That destroys the layout of the table view. You should never touch the frames of the cells from the outside.
If you want to set the height of your cells you have to do that in the UITableViewDelegate
method tableView(_:heightForRowAtIndexPath:)
. Calculate the cell height there and return it.
You do not have to set the width of your cells, because in a UITableView
the UITableViewCells
always have the same width as the UITableView
.
Upvotes: 2