【问题标题】:IOS: UICollectionView UIButtons are not workingIOS:UICollectionView UIButtons 不工作
【发布时间】:2023-03-07 10:23:01
【问题描述】:

在我的项目中,我使用UICollectionView 来显示数据。数据完美显示在UICollectionViewCells 中,但我也在单元格中使用“编辑”和“删除”按钮来编辑或删除数据。

当我尝试编辑任何单元格并按下“编辑”按钮时会出现问题。它仅适用于前 3 个单元格。当我单击第四个单元格的编辑按钮时,它会在编辑页面上显示第一个单元格的结果,对于第五个单元格,它显示第二行的结果,对于第 6 个单元格,它显示第三行的内容,然后对于第 7 行,它再次显示第一行的结果单元格,这个过程一直持续到单元格结束。

编辑函数

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {

        static NSString *identifier = @"cellIdentifier";
        UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

       editbtn = (UIButton *)[cell.contentView viewWithTag:206];
        editbtn.tag = indexPath.row;
        [editbtn addTarget:self action:@selector(editprocedure:) forControlEvents:UIControlEventTouchUpInside];
        [editbtn setTintColor:[UIColor blackColor]];

        deletebtn = (UIButton *)[cell.contentView viewWithTag:207];
        [deletebtn addTarget:self action:@selector(deleteprocedure:) forControlEvents:UIControlEventTouchUpInside];
        [deletebtn setTintColor:[UIColor blackColor]];
        deletebtn.tag = indexPath.row;

        return cell;
    }

我还分享了模拟器上的截图

这是编辑功能的代码

-(IBAction)editprocedure:(UIButton*)sender
{
    UIButton *btnTapped = (UIButton *)sender;
    self.strdiagid = btnTapped.accessibilityIdentifier;
    NSLog(@"str ID : %@",self.strdiagid);

    self.strdiagid = [CompletephyDic objectForKey:@"id"];
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
    EditProcedureVC *vch = [mainStoryboard instantiateViewControllerWithIdentifier:@"EditProcedureVC"];

    self.strdiagid = [CompletephyDic objectForKey:@"id"];
    NSString * a = self.strdiagid;
    NSLog(@"id...%@",a);

    vch.stridd = a; //stridd is the id of the procedure which is transferred to other view
    vch.infoDictionary = [dataArray objectAtIndex:sender.tag];

    [self presentViewController:vch animated:NO completion:nil];
}

【问题讨论】:

  • 对于第四个单元格,按钮操作是否调用?如果不是,请检查 collectionview 中的单元格大小。
  • 单元格数据来自api,collectionview中大约有15个单元格。通过上面的代码,编辑按钮对前 3 个单元格运行良好,但对于第四个单元格,它显示第一个单元格的内容
  • 这是由于collectionView的重用单元格的行为,如果您可以分享editprocedure,deleteprocedure的代码,我可能会帮助您。
  • 请再检查一次我更新了我的问题也请点赞,以便我可以添加截图并使用本网站的更多功能
  • 你在这一行犯了错误 vch.infoDictionary = [dataArray objectAtIndex:sender.tag];您的按钮标签是 206 和 207,因此您得到了错误的数据。

标签: ios objective-c uibutton uicollectionview uicollectionviewcell


【解决方案1】:

很遗憾,所选答案对我不起作用。以下是所做的记录:

我花了好几个小时在网上搜索我的 UIButton 在 UICollectionView 中不起作用的解决方案。让我发疯,直到我终于找到适合我的解决方案。而且我相信这也是正确的方法:破解命中测试。这是一个比修复 UICollectionView 按钮问题更深入(双关语)的解决方案,因为它可以帮助您将点击事件发送到隐藏在阻止您的事件通过的其他视图下的任何按钮:

UIButton in cell in collection view not receiving touch up inside event

由于 SO 答案是在 Objective C 中,我从那里找到了一个快速解决方案的线索:

http://khanlou.com/2018/09/hacking-hit-tests/

--

当我禁用单元格上的用户交互或我尝试的任何其他各种答案时,没有任何效果。

我在上面发布的解决方案的美妙之处在于,您可以保留 addTarget 和选择器函数的习惯,因为它们很可能永远不会成为问题。您只需要重写一个函数来帮助触摸事件到达目的地。

解决方案为何有效:

在最初的几个小时里,我发现我的 addTarget 调用没有正确注册手势。事实证明,目标注册良好。触摸事件根本就没有到达我的按钮。

现实似乎来自我阅读的任何数量的 SO 帖子和文章,即 UICollectionView 单元旨在容纳一个动作,而不是出于各种原因的多个动作。所以你只是应该使用内置的选择动作。考虑到这一点,我相信绕过此限制的正确方法不是破解 UICollectionView 以禁用滚动或用户交互的某些方面。 UICollectionView 只是在做它的工作。 正确的方法是破解命中测试以在点击到达 UICollectionView 之前拦截点击并找出他们正在点击的项目。然后,您只需向他们正在点击的按钮发送一个触摸事件,然后让您的正常工作完成。


我的最终解决方案(来自 khanlou.com 文章)是将我的 addTarget 声明和我的选择器函数放在我喜欢的任何位置(在单元格类或 cellForItemAt 覆盖中),并在覆盖 hitTest 函数的单元格类中。

在我的单元格中,我有:

@objc func didTapMyButton(sender:UIButton!) {
    print("Tapped it!")
}

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

    guard isUserInteractionEnabled else { return nil }

    guard !isHidden else { return nil }

    guard alpha >= 0.01 else { return nil }

    guard self.point(inside: point, with: event) else { return nil }


    // add one of these blocks for each button in our collection view cell we want to actually work
    if self.myButton.point(inside: convert(point, to: myButton), with: event) {
        return self.myButton
    }

    return super.hitTest(point, with: event)
}

在我的单元类初始化中,我有:

self.myButton.addTarget(self, action: #selector(didTapMyButton), for: .touchUpInside)

【讨论】:

    【解决方案2】:

    试试这个

    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:YES];
    
        [self setAutomaticallyAdjustsScrollViewInsets:NO];
    }
    

    【讨论】:

    • 请为我的问题投票,以便我能够提出新问题
    【解决方案3】:

    子类 UICollectionViewCell 并将您的 collectionViewCell 的自定义类设置为情节提要上的这个子类。制作EditButton和DeleteButton的出口。

    用 indexPath 行或部分替换按钮的标签,并按以下方式访问它:-

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        CustomCollectionViewCells *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cvCells" forIndexPath:indexPath];
        [cell.editButton setTag:indexPath.row];
        [cell.button addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
        }
    
    - (IBAction)clicked:(id)sender {
    
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
    
        CustomCollectionViewCell *cell = (CustomCollectionViewCell *) [self.collectionview cellForItemAtIndexPath:indexPath];
              //Your desired code for the specific cell
        }
    

    希望对您有所帮助。如果您有任何疑问,请告诉我。

    【讨论】:

      【解决方案4】:

      试试这个:

       - (void)prepareForReuse {
              [super prepareForReuse];
              //Reset your components to nil here.
          }
      

      【讨论】:

      • 在哪里调用这个函数?这给出了一个错误“没有可见的@interface for.......声明选择器'PrepareForReuse'”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 2015-03-23
      • 2014-06-07
      • 2015-08-08
      相关资源
      最近更新 更多