IOS: UICollectionView UIButtons 不工作
IOS: UICollectionView UIButtons are not working
在我的项目中,我使用 UICollectionView
来显示数据。数据完美地显示在 UICollectionViewCells
中,但我还在单元格中使用 "Edit" 和 "Delete" 按钮来编辑或删除数据。
当我尝试编辑任何单元格并按下 "edit" 按钮时出现问题。它仅适用于前 3 个单元格。当我单击第四个单元格的编辑按钮时,它会在编辑页面上显示第一个单元格的结果,对于第五个单元格,它显示第二行的结果,对于第六个单元格,它显示第三行的内容,然后对于第七行,它再次显示第一行的结果单元格,此过程一直持续到单元格结束。
编辑功能
- (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];
}
试试这个:
- (void)prepareForReuse {
[super prepareForReuse];
//Reset your components to nil here.
}
Subclass UICollectionViewCell 并将您的 collectionViewCell 的自定义 class 设置为故事板上的此子classed class。制作 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
}
希望对您有所帮助。如果您有任何疑问,请告诉我。
试试这个
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self setAutomaticallyAdjustsScrollViewInsets:NO];
}
很遗憾,所选答案对我不起作用。这是对所做事情的记录:
我花了几个小时在网上搜索我的 UIButton 在 UICollectionView 中无法正常工作的解决方案。让我发疯,直到我终于找到适合我的解决方案。而且我相信这也是正确的方法:破解命中测试。这是一个比修复 UICollectionView 按钮问题更深入(双关语意)的解决方案,因为它可以帮助您将点击事件发送到埋在其他视图下的任何按钮,这些按钮阻止您的事件通过:
UIButton in cell in collection view not receiving touch up inside event
由于 SO 答案在 Objective C 中,我按照那里的线索找到了 swift 解决方案:
http://khanlou.com/2018/09/hacking-hit-tests/
--
当我禁用单元格上的用户交互或我尝试过的任何其他各种答案时,没有任何效果。
我在上面发布的解决方案的美妙之处在于,您可以让您的 addTarget 和选择器函数按照您习惯的方式使用,因为它们很可能永远不会成为问题。您只需覆盖一个函数即可帮助触摸事件到达目的地。
解决方案为何有效:
在最初的几个小时里,我认为我的 addTarget 调用没有正确注册该手势。事实证明目标没有问题。触摸事件根本就没有到达我的按钮。
事实似乎是从我读过的许多 SO 帖子和文章来看,UICollectionView Cells 是用来容纳一个动作的,而不是出于多种原因的多个动作。所以你只是应该使用内置的选择操作。考虑到这一点,我认为绕过此限制的正确 方法不是破解 UICollectionView 以禁用滚动或用户交互的某些方面。 UICollectionView 只是在做它的工作。 正确的 方法是破解命中测试以在它到达 UICollectionView 之前拦截点击并找出他们正在点击的项目。然后,您只需向他们正在点击的按钮发送一个触摸事件,然后让您的正常工作来完成工作。
我的最终解决方案(来自 khanlou.com 文章)是将我的 addTarget 声明和我的选择器函数放在我喜欢的任何地方(在单元格 class 或 cellForItemAt 覆盖中),并在单元格中class 重写 hitTest 函数。
在我的手机里 class 我有:
@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)
}
在我的单元格 class init 中,我有:
self.myButton.addTarget(self, action: #selector(didTapMyButton), for: .touchUpInside)
在我的项目中,我使用 UICollectionView
来显示数据。数据完美地显示在 UICollectionViewCells
中,但我还在单元格中使用 "Edit" 和 "Delete" 按钮来编辑或删除数据。
当我尝试编辑任何单元格并按下 "edit" 按钮时出现问题。它仅适用于前 3 个单元格。当我单击第四个单元格的编辑按钮时,它会在编辑页面上显示第一个单元格的结果,对于第五个单元格,它显示第二行的结果,对于第六个单元格,它显示第三行的内容,然后对于第七行,它再次显示第一行的结果单元格,此过程一直持续到单元格结束。
编辑功能
- (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];
}
试试这个:
- (void)prepareForReuse {
[super prepareForReuse];
//Reset your components to nil here.
}
Subclass UICollectionViewCell 并将您的 collectionViewCell 的自定义 class 设置为故事板上的此子classed class。制作 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
}
希望对您有所帮助。如果您有任何疑问,请告诉我。
试试这个
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self setAutomaticallyAdjustsScrollViewInsets:NO];
}
很遗憾,所选答案对我不起作用。这是对所做事情的记录:
我花了几个小时在网上搜索我的 UIButton 在 UICollectionView 中无法正常工作的解决方案。让我发疯,直到我终于找到适合我的解决方案。而且我相信这也是正确的方法:破解命中测试。这是一个比修复 UICollectionView 按钮问题更深入(双关语意)的解决方案,因为它可以帮助您将点击事件发送到埋在其他视图下的任何按钮,这些按钮阻止您的事件通过:
UIButton in cell in collection view not receiving touch up inside event
由于 SO 答案在 Objective C 中,我按照那里的线索找到了 swift 解决方案:
http://khanlou.com/2018/09/hacking-hit-tests/
--
当我禁用单元格上的用户交互或我尝试过的任何其他各种答案时,没有任何效果。
我在上面发布的解决方案的美妙之处在于,您可以让您的 addTarget 和选择器函数按照您习惯的方式使用,因为它们很可能永远不会成为问题。您只需覆盖一个函数即可帮助触摸事件到达目的地。
解决方案为何有效:
在最初的几个小时里,我认为我的 addTarget 调用没有正确注册该手势。事实证明目标没有问题。触摸事件根本就没有到达我的按钮。
事实似乎是从我读过的许多 SO 帖子和文章来看,UICollectionView Cells 是用来容纳一个动作的,而不是出于多种原因的多个动作。所以你只是应该使用内置的选择操作。考虑到这一点,我认为绕过此限制的正确 方法不是破解 UICollectionView 以禁用滚动或用户交互的某些方面。 UICollectionView 只是在做它的工作。 正确的 方法是破解命中测试以在它到达 UICollectionView 之前拦截点击并找出他们正在点击的项目。然后,您只需向他们正在点击的按钮发送一个触摸事件,然后让您的正常工作来完成工作。
我的最终解决方案(来自 khanlou.com 文章)是将我的 addTarget 声明和我的选择器函数放在我喜欢的任何地方(在单元格 class 或 cellForItemAt 覆盖中),并在单元格中class 重写 hitTest 函数。
在我的手机里 class 我有:
@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)
}
在我的单元格 class init 中,我有:
self.myButton.addTarget(self, action: #selector(didTapMyButton), for: .touchUpInside)