转载

那些年,我踩过的坑(二)

最近踩到一个坑,表现状况如下:

UICollectionView的Cell中有一个UIImageView,有选中和未选中两个状态。在某种条件下点击时是不做任何改变的(即保持未选中状态)。

起初的做法是:

将UIImageView的 imagehightedImage 属性和cell的选中/未选中状态进行绑定,通过UIImageView的 setHighlighted: 方法来切换选中状态。

// MyController.m - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {     if (conditionAIsSatisfied) {         ......     } }  // MyCollectionViewCell.m - (void)updateCellWithSelected:(BOOL)selected {     [_imgView setHighlighted:selected]; } 

存在的问题是:

在UICollectionView的 didSelectItemAtIndexPath: 方法中,即使不执行if语句中的更新imageView的方法, _imgView 也会更新为选中状态的图片。而collectionViewCell中的 updateCellWithSelected: 也是没有执行的。那么,为什么 _imgView 的图片会更新呢?

类似的,在UITableView中做同样的控制,UITableViewCell中 _imgView 的图片为什么就不会改变呢?

UICollectionViewDelegate 中相关的各个回调方法如下。

// Methods for notification of selection/deselection and highlight/unhighlight events.

// The sequence of calls leading to selection from a user touch is:

//

// (when the touch begins)

// 1. -collectionView:shouldHighlightItemAtIndexPath:

// 2. -collectionView:didHighlightItemAtIndexPath:

//

// (when the touch lifts)

// 3. -collectionView:shouldSelectItemAtIndexPath: or -collectionView:shouldDeselectItemAtIndexPath:

// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:

// 5. -collectionView:didUnhighlightItemAtIndexPath:

UICollectionViewCell并没有像UITableViewCell一样提供类似 selectionStyle 的属性来直接将选中时的样式设置为 UITableViewCellSelectionStyleNone ,而是给了开发者更多的灵活性,提供了更多的代理方法。通过查看 UICollectionViewDelegate 以及在 shouldSelectItemAtIndexPath:didHighlightItemAtIndexPath: 等函数中打断点逐个排查,发现cell的highlighted和imageview的highlighted是关联的。当cell被选中时,虽然 didSelectItemAtIndexPath: 方法并没有执行实质性的代码,但在其之前执行的 shouldHighlightItemAtIndexPath: 方法默认为 YES ,使整个cell的状态为highlighted,相应的imageView的状态就是显示highlighted的图片了。

知道了原因之后,总结了两个解决方案:

1.添加 shouldSelectItemAtIndexPath: 方法,在其中增加 conditionAIsSatisfied 的判断,来对应地返回 YESNO

2.在 MyCollectionViewCell 中,不再为UIImageView的 imagehightedImage 设置不同的图片,而是设置为同一个图片。然后在 -updateCellWithSelected: 中根据 selected 值来替换选中/未选中的图片。

对比来看,1的缺点在于,已选中的cell无法取消选中。2的缺点在于,切换图片时会有点突兀。

综合考量,我最后选择了方案2。

Update 0420

但是,上面啰嗦了半天,其实只需要一句代码解决问题:

collectionView.allowSelection = NO; 

来自 这里 。UITableView同理。

果然是简洁至上。

原文  http://www.calios.gq/2016/04/20/那些年,我踩过的坑(二)/
正文到此结束
Loading...