I am using this code: https://www.youtube.com/watch?v=bNtsekO51iQ , but when I implement my data and use collectionView.reloadData() it crashes with error code *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the collection view's data source did not return a valid cell from -collectionView:cellForItemAtIndexPath: for index path <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}'
class ChatLogController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var userId:Int?
var position:Int = 0
var otherAvatar:UIImage = UIImage(named: "defaultAvatar")!
var otherName:String = ""
var otherSex:String = ""
var otherBanned:Int = 0
var otherBlocked:Int = 0
var messagesDates:[String] = []
var messagesText:[String] = []
var messagesIds:[String] = []
var messagesPics:[UIImage?] = []
var messagesSeen:[Int] = []
var messagesWhoSendIt:[Int] = []
private let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.register(ChatLogMessageCell.self, forCellWithReuseIdentifier: cellId)
collectionView!.isPrefetchingEnabled = false
loadChatsFor(position: position)
} override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messagesIds.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath as IndexPath) as! ChatLogMessageCell
cell.messageTextView.text = messagesText[indexPath.row]
cell.profileImageView.image = UIImage(named: "defaultAvatar")!
let size = CGSize(width:250,height:1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: messagesText[indexPath.row]).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil)
cell.messageTextView.frame = CGRect(x:48 + 8, y:0, width:estimatedFrame.width + 16, height:estimatedFrame.height + 20)
cell.textBubbleView.frame = CGRect(x:48, y:0, width:estimatedFrame.width + 16 + 8, height:estimatedFrame.height + 20)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width:250,height:1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: messagesText[indexPath.row]).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil)
return CGSize(width:view.frame.width, height:estimatedFrame.height + 20)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(8, 0, 0, 0)
}
}
class ChatLogMessageCell: BaseCell {
let messageTextView: UITextView = {
let textView = UITextView()
textView.font = UIFont.systemFont(ofSize: 18)
textView.text = "Sample message"
textView.backgroundColor = UIColor.clear
return textView
}()
let textBubbleView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0.95, alpha: 1)
view.layer.cornerRadius = 15
view.layer.masksToBounds = true
return view
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 15
imageView.layer.masksToBounds = true
return imageView
}()
override func setupViews() {
super.setupViews()
addSubview(textBubbleView)
addSubview(messageTextView)
addSubview(profileImageView)
addConstraintsWithFormat(format:"H:|-8-[v0(30)]", views: profileImageView)
addConstraintsWithFormat(format:"V:[v0(30)]|", views: profileImageView)
profileImageView.backgroundColor = UIColor.red
}
}
extension UIView {
func addConstraintsWithFormat(format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated() {
let key = "v\(index)"
viewsDictionary[key] = view
view.translatesAutoresizingMaskIntoConstraints = false
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
}
class BaseCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
}
}
In loadChatsFor I get the array data from web and I use collectionView.reloadData(), but when this function is performed it crashes my app. I've searched for answer, but unsuccessfully. I've added IOS 10 function collectionView!.isPrefetchingEnabled = false in view did load from this answer UICollectionView exception in UICollectionViewLayoutAttributes from iOS7, but also not working. Even the method collectionViewLayout invalidateLayout before reloadData and after reloadData doesn't stop the crash. So what else I can do to make it work ?
I am coming in this CollectionViewController from UITableViewCell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let layout = UICollectionViewFlowLayout()
let controller = ChatLogController(collectionViewLayout: layout)
controller.userId = chatUserIds[indexPath.row]
navigationController?.pushViewController(controller, animated: true)
}
I've added UICollectionViewDelegateFlowLayout in the class of the tableview