在我的应用中,我有一个UICollectionView
,可以在我的应用中充当滚动颜色选择器。我有一个非常罕见的错误,一旦在蓝色的月亮,按钮按下时颜色将被设置为滚动条中的第一个值,而不是与用户实际触摸的按钮相关联的颜色。
我将此信息隔离到indexPathForItemAtPoint
返回nil
按钮按下。
现在我只是在返回的索引路径为nil
时返回来解决问题,但是,我担心这种行为仍然不正确有几个原因;
UIControlEventTouchUpInside
时,会发生获取与按钮关联的颜色的触发器。因此,对我来说没有意义的是,代码将被调用而不是按钮内的触摸。在这种情况下,我已经交换了我当前的错误颜色,因为一个按钮几乎不会响应的错误。 我做了一些搜索,除非我错过了,我在这个网站上看到的只是代码有一个实现错误并且总是接收nil的情况,但没有什么比这更好。
我希望有人能够帮助我找出原因,以便我可以解决它或至少理解问题发生的原因。
相关功能如下:
- (IBAction)myClickEvent:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView: self.collectionViewColors];
NSIndexPath *indexPath = [self.collectionViewColors indexPathForItemAtPoint: currentTouchPosition];
if(!indexPath)return;
appState.currentColor = appState.colors[indexPath.row];
const CGFloat *components = CGColorGetComponents(appState.currentColor.CGColor);
self.redSlider.value = components[0];
self.greenSlider.value = components[1];
self.blueSlider.value = components[2];
appState.setBackgroundImagePreview(nil);
}
设置按钮事件的初始化函数:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIButton *myButton = (UIButton *)[cell viewWithTag:100];
[myButton addTarget:self action:@selector(myClickEvent:event:) forControlEvents:UIControlEventTouchUpInside];
/// abridged
[myButton setBackgroundImage:colorSquare forState:UIControlStateNormal];
return cell;
}
谢谢!
编辑:我尝试了下面的操作,认为Apple可能会出于某种原因在按钮外发送多点触控/触摸。没有骰子。它有时仍返回nil
索引路径。
NSSet *touches = [event touchesForView:sender];
答案 0 :(得分:3)
indexPathForItemAtPoint:
会返回nil
当点落在单元格之间的间距时,最常见的情况。有3个流布局属性通常用于影响单元格的间距:
minimumLineSpacing
minimumInteritemSpacing
sectionInset
获得nil
索引路径然后询问其行时,它始终为0
,因此appState.colors[indexPath.row]
为您提供阵列中的第一种颜色。
解决此问题的一种方法是循环遍历indexPathsForVisibleItems
中的所有单元格,并确定哪一个包含中心点(如果有)或最接近它。最简单的方法是使用
- layoutAttributesForItemAtIndexPath:
,CGRectContainsPoint()
和一些简单的数学运算。
如果您获得return
路径并且不采取任何措施,那么您的应用只需nil
就可以了。