Ios UICollectionView选择并取消选择问题

Ios UICollectionView选择并取消选择问题,ios,cocoa-touch,uicollectionview,Ios,Cocoa Touch,Uicollectionview,所以我有一个主要的对象,它有许多与之相关的图像。图像也是一个对象 假设您有一个集合视图控制器,并且在该控制器中有 cellForItemAtIndexPath 基于主对象,如果它有与之关联的当前图像,我想将selected设置为true。但我希望用户能够随时“取消选择”当前单元格,以删除其与主对象的关联 我发现,如果将“selected设置为true”-如果在cellForItemAtIndexPath中的主对象和图像之间存在关系,则取消选择不再是一个选项 在 及 我使用日志进行测试,以查看是否

所以我有一个主要的对象,它有许多与之相关的图像。图像也是一个对象

假设您有一个集合视图控制器,并且在该控制器中有

cellForItemAtIndexPath

基于主对象,如果它有与之关联的当前图像,我想将selected设置为true。但我希望用户能够随时“取消选择”当前单元格,以删除其与主对象的关联

我发现,如果将“selected设置为true”-如果在
cellForItemAtIndexPath
中的主对象和图像之间存在关系,则取消选择不再是一个选项

我使用日志进行测试,以查看是否调用了它们。如果某个单元格设置为selected,则会调用nether,但如果我从未在
cellForItemAtIndexPath
中将某个单元格设置为selected,则我可以选择并取消选择所需的所有单元格

这是集合视图的预期工作方式吗?我读了文件,但它似乎没有提到这一点。我对文档的理解是,它的工作方式与表视图单元格的工作方式相同。有一些明显的变化


这也表明控制器设置正确,并且正在使用适当的委托方法。。。。hmmmm

我不知道我是否理解这个问题,但是选择的状态是按单元格设置的,并且将包括单元格中的所有子视图。你没有解释你所说的“一个主对象有许多与之相关联的图像”是什么意思。与子视图相关吗?或者你的确切意思是什么样的联系

对我来说,这听起来像是一个设计问题。也许您需要一个UIView子类,它包含您需要的任何关联对象;然后可以将该子类设置为内容视图。我这样做,例如,我有一个图像,一个描述,和一个与图像相关的录音。所有这些都在子类中定义,然后这些子类中的每个都成为单个单元格的内容视图

我还使用了一种安排,将图像关联到包含它们的文件夹中。在此设置下,文件夹和图像都有一个子类,其中任何一个子类都可以作为内容视图附加到单元格(它们作为单个实体存储在核心数据中)

也许您可以进一步解释您的问题?

您是否看过:

- (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
请把你的问题说得更清楚些,也许我们能找到问题的根源。我刚刚在UICollectionView上花了一些时间


我认为您的问题可能源于这样一种混淆:如果您以编程方式设置
cell.selected=YES
,则不会调用
didSelectItemAtIndexPath:
,因为只有在collectionView本身负责单元格的选择时(例如通过点击)才会使用该选项。

我也有同样的问题,例如,在
[UICollectionView collectionView:cellForItemAtIndexPath:][/code>中设置
cell.selected=YES
,然后无法通过点击来取消选择单元格


目前的解决方案:我在
[UICollectionView collectionView:cellForItemAtIndexPath:
中调用
[uiCollectionViewCellSetSelected:
[UICollectionView selectItemAtIndexPath:animated:scrollPosition:
两种方法,在单元格类中是否有自定义的
setSelected
方法?你是在用那种方法调用
[super-setSelected:selected]


我有一个神秘的问题,当我使用多重选择时,一旦选择了单元格,我就无法取消选择。调用超级方法修复了问题。

我在
UICollectionView
中遇到了取消选择问题,我发现我不允许在collectionView上进行多次选择。所以,当我测试时,我总是在同一个单元格上尝试,如果启用了“单一选择”,则无法取消选择已选择的单元格

我必须补充:

myCollectionView.allowsMultipleSelection = YES;

我不知道为什么与
UITableViewController
相比,
UICollectionView
如此混乱。。。 我发现了一些事情

之所以多次调用
setSelected:
是因为调用了sequence方法。该顺序与
UITextFieldDelegate
方法的顺序非常相似

方法
collectionView:shouldSelectItemAtIndexPath:
collectionView
实际选择单元格之前被调用,因为它实际上在询问“是否应该选择它”

collectionView:didSelectItemAtIndexPath:
实际上是在
collectionView
选择单元格后调用的。因此命名为“did select”

这就是你的情况(还有我的情况,我不得不为此奋斗数小时)

用户再次触摸选定单元格以取消选择
shouldSelectItemAtIndexPath:
被调用以检查是否应选择单元格。
collectionView
选择单元格,然后调用
didSelectItemAtIndexPath
。此时所做的任何操作都是在单元格的
selected
属性设置为
YES
之后进行的。这就是为什么类似于
cell.selected=!单元格。选定的
将不起作用

TL;DR-通过调用
deselectItemAtIndexPath:animated:
并返回
NO
,让您的
collectionView
取消选择委托方法中的单元格
collectionView:shoulldSelectItemAtIndexPath:

我所做的简短示例:

- (BOOL)collectionView:(OPTXListView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *selectedItemIndexPaths = [collectionView indexPathsForSelectedItems];

    if ([selectedItemIndexPaths count]) {
        NSIndexPath *selectedIndexPath = selectedItemIndexPaths[0];

        if ([selectedIndexPath isEqual:indexPath]) {
            [collectionView deselectItemAtIndexPath:indexPath animated:YES];

            return NO;
        } else {
            [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

            return YES;
        }
    } else {
        [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

        return YES;
    }
}

这有点陈旧,但是,由于我使用swift遇到相同的问题,我将添加我的答案。 使用时:

 collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])
cell.selected = true
该单元格根本没有被选中。但在使用时:

 collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])
cell.selected = true
它确实被选中了,但我无法再选择/取消选择单元格

我的解决方案(使用两种方法):

在调用这两个方法时:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

它工作得很好

单元格选择和取消选择最好通过设置背景视图和选定背景视图来处理。我建议确保在layoutSubviews方法中正确设置了这两个视图的框架(如果需要)
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
collectionView.allowsMultipleSelection = true;
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}
class MyCell : UICollectionViewCell {

    ....

    func toggleSelected ()
    {
        if (selected){
            backgroundColor = UIColor.orangeColor()
        }else {
            backgroundColor = UIColor.whiteColor()
        }
    }

}
 func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == true{
        cell?.layer.borderWidth = 4.0
         cell?.layer.borderColor = UIColor.greenColor().CGColor
    }   
}func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath)
    if cell?.selected == false{
            cell?.layer.borderColor = UIColor.clearColor().CGColor
    }

}
(lldb) po cell.selectedBackgroundView
<UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>

(lldb) po cell.contentView
<UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>

(lldb) pviews cell
<MyCell: 0x7fd2dae1aa70; baseClass = UICollectionViewCell; frame = (0 0; 64 49.5); clipsToBounds = YES; hidden = YES; opaque = NO; layer = <CALayer: 0x7fd2dae1ac80>>
   | <UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>>
   | <UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>>
   |    | <UIView: 0x7fd2dae24a60; frame = (0 0; 64 49.5); clipsToBounds = YES; alpha = 0; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7fd2dae1acc0>>
   |    | <UILabel: 0x7fd2dae24bd0; frame = (0 0; 64 17.5); text = '1'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae240c0>>
   |    | <UILabel: 0x7fd2dae25030; frame = (0 21.5; 64 24); text = '1,04'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae25240>>

(lldb) po cell.contentView.backgroundColor
UIDeviceRGBColorSpace 0.4 0.4 0.4 1
cell.backgroundColor = SOME_COLOR;
cell.contentView.backgroundColor = [UIColor clearColor];
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier:"MyCell", for: indexPath) as? MyCell else { return UICollectionViewCell() }
        
        cell.setupCellStyle(isSelected: false)
        
        return cell
    }

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) else { return }
        cell.setupCellStyle(isSelected: true)
    }
    
    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) else { return }
        cell.setupCellStyle(isSelected: false)
    }
class MyCell: UICollectionViewCell {
        func setupCellStyle(isSelected: Bool) {
            if(isSelected) {
                self.contentView.backgroundColor = UIColor.blue
            } else {
                self.contentView.backgroundColor = UIColor.green
            }
        }
    }