Swift 3 - CollectionView 数据源未返回有效单元格
Posted
技术标签:
【中文标题】Swift 3 - CollectionView 数据源未返回有效单元格【英文标题】:Swift 3 - CollectionView data source did not return a valid cell 【发布时间】:2017-06-27 15:25:23 【问题描述】:我正在使用此代码:https://www.youtube.com/watch?v=bNtsekO51iQ,但是当我实现我的数据并使用 collectionView.reloadData() 时,它会崩溃并出现错误代码 *** 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()
在 loadChatsFor 中,我从 web 获取数组数据并使用 collectionView.reloadData(),但是当执行此函数时,它会使我的应用程序崩溃。我一直在寻找答案,但没有成功。我添加了 ios 10 函数 collectionView!.isPrefetchingEnabled = false 视图确实从这个答案UICollectionView exception in UICollectionViewLayoutAttributes from iOS7 加载,但也没有工作。即使在 reloadData 之前和 reloadData 之后的方法 collectionViewLayout invalidateLayout 也不能阻止崩溃。那么我还能做些什么来让它发挥作用呢?
我从 UITableViewCell 进入这个 CollectionViewController
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)
我在tableview的类中添加了UICollectionViewDelegateFlowLayout
【问题讨论】:
【参考方案1】:您没有实现正确的cellForItemAt
方法UICollectionViewDataSource
。这个方法的签名在 Swift 3 中是这样改变的。
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> 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
【讨论】:
我点击迁移到 Swift 3,但这可能是 XCode 8.1 中的错误,非常感谢 :)以上是关于Swift 3 - CollectionView 数据源未返回有效单元格的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3 - CollectionView 数据源未返回有效单元格
Swift 3.0:自定义CollectionView标题按钮单击
SWIFT 3:将不同的声音文件数组匹配到 CollectionView 中的每个部分
Swift 3:在 CollectionView 中选择时放大图像