Ios 将集合视图中的单元格移动到另一节的最后一个单元格之外是不可行的
为了能够在集合视图中移动/平移单元格,应实现UIgestureRecognitor。这在单个截面集合视图中工作良好。但是,在多节集合视图中,当单元格平移/移动到另一节的最后一个单元格之外时,会发生错误。 尽管在平移过程中正确触发“cellForItemAtIndexPath”以显示“新”单元格,但在平移超过最后一个可用单元格后不应触发它(即,在这种情况下,indexath.row==numberOfItemsInSection并导致错误(见下面的代码)) 在表视图中,(默认)移动/平移实现不会出现此问题 这可能是Swift中的一个错误吗?是否有人建议在平移到区域中最后一个单元格之外时避免触发“cellForItemAtIndexPath” 下面是Swift 2.3中的工作代码示例,以说明该问题Ios 将集合视图中的单元格移动到另一节的最后一个单元格之外是不可行的,ios,uicollectionview,uigesturerecognizer,Ios,Uicollectionview,Uigesturerecognizer,为了能够在集合视图中移动/平移单元格,应实现UIgestureRecognitor。这在单个截面集合视图中工作良好。但是,在多节集合视图中,当单元格平移/移动到另一节的最后一个单元格之外时,会发生错误。 尽管在平移过程中正确触发“cellForItemAtIndexPath”以显示“新”单元格,但在平移超过最后一个可用单元格后不应触发它(即,在这种情况下,indexath.row==numberOfItemsInSection并导致错误(见下面的代码)) 在表视图中,(默认)移动/平移实现不会出
class CustomViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
private var list = ["one", "two", "three","four","five","six","seven","eight"]
private var itemsList: [[String]]!
private var collectionView : UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
itemsList = [list, list, list] // Create three sections
collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: UICollectionViewFlowLayout())
self.collectionView.dataSource = self
self.collectionView.delegate = self
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.registerClass(CustomCell.self, forCellWithReuseIdentifier: "cell")
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(CustomViewController.handleGesture(_:)))
self.collectionView.addGestureRecognizer(panGesture)
self.view.addSubview(self.collectionView)
}
override func viewWillLayoutSubviews() {
let margins = view.layoutMarginsGuide
self.collectionView.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor, constant: 0).active = true
self.collectionView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor, constant: 0).active = true
self.collectionView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: 0).active = true
self.collectionView.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 0).active = true
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return itemsList.count
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return itemsList[section].count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CustomCell
let items = itemsList[indexPath.section]
cell.label.text = items[indexPath.row] // The error occurs here, after panning beyond the last cell of another section stating: "fatal error: Index out of range"
return cell
}
func collectionView(collectionView: UICollectionView, canMoveItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
let itemToMove = itemsList[sourceIndexPath.section][sourceIndexPath.row]
itemsList[sourceIndexPath.section].removeAtIndex(sourceIndexPath.row)
itemsList[destinationIndexPath.section].insert(itemToMove, atIndex: destinationIndexPath.row)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSizeMake(collectionView.bounds.size.width, 50)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(collectionView.bounds.size.width, 40)
}
func handleGesture(gesture: UIPanGestureRecognizer) {
switch(gesture.state) {
case UIGestureRecognizerState.Began:
guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {
break }
collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
case UIGestureRecognizerState.Changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
case UIGestureRecognizerState.Ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}
}
class CustomCell: UICollectionViewCell {
var label: UILabel!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.whiteColor()
self.label = UILabel()
self.label.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(self.label)
}
override func layoutSubviews() {
super.layoutSubviews()
let margins = self.contentView.layoutMarginsGuide
self.label.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = true
self.label.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true
self.label.centerYAnchor.constraintEqualToAnchor(self.contentView.centerYAnchor).active = true
}
}
根据苹果公司的说法,我的问题中描述的问题是iOS中的一个bug,并且似乎在iOS 10 beta(xcode 8 GM)的当前版本中得到了解决
不幸的是,集合视图的其他问题还没有解决,例如基本支持将项目移动到空部分 “发生错误”什么错误?你说“问题发生在这里”,但你是抛出
致命错误的人。那么问题出在哪里呢?当indexPath.row>itemsList[indexPath.section].count时会发生错误,这是在平移另一个节中的最后一个单元格之后产生的。我更新了代码。但是现在我不知道错误在哪一行。你的意思是让items=itemsList[indexPath.section]
?那么,您是否调试并查看了indexPath.section
实际上是什么?错误发生在items[indexPath.row]
处。就在错误发生之前,IndexPath是{length=2,path=1-8}
。使用此indexPath,cellForItemAtIndexPath
不应被触发。因此,我觉得这可能是一个bug。是否可以尝试使用targetIndexPathForMoveFromItem
实现防止触发它?