iPhone:跟踪/识别个人接触

时间:2009-05-26 22:26:49

标签: iphone cocoa-touch uikit multi-touch

我有一个关于在iPhone上跟踪触摸的快速问题,我似乎无法就此得出结论,因此非常感谢任何建议/想法:

我希望能够跟踪和识别iPhone上的触摸,即。基本上每个触摸都有一个起始位置和一个当前/移动位置。触摸存储在std :: vector中,一旦结束,它们将从容器中删除。他们的位置一旦移动就会更新,但我仍想跟踪他们最初的起点(手势识别)。

我从[event allTouches]获得了接触,事实是,NSSet未排序,我似乎无法识别已经存储在std :: vector中的触摸并引用NSSet中的触摸(所以我知道哪些已经结束,将被移除,或者已被移动等等)

这是我的代码,当然,它只能在触摸屏上只用一根手指完美地工作,但是不止一个,我确实得到了不可预测的结果......

    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self handleTouches:[event allTouches]];
}

- (void) handleTouches:(NSSet*)allTouches
{   
    for(int i = 0; i < (int)[allTouches count]; ++i)
    {
        UITouch* touch = [[allTouches allObjects] objectAtIndex:i];
        NSTimeInterval timestamp = [touch timestamp];

        CGPoint currentLocation = [touch locationInView:self];
        CGPoint previousLocation = [touch previousLocationInView:self];

        if([touch phase] == UITouchPhaseBegan)
        {
            Finger finger;
            finger.start.x = currentLocation.x;
            finger.start.y = currentLocation.y;
            finger.end = finger.start;
            finger.hasMoved = false;
            finger.hasEnded = false;

            touchScreen->AddFinger(finger);
        }
        else if([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.hasEnded = true;
        }
        else if([touch phase] == UITouchPhaseMoved)
        {
            Finger& finger = touchScreen->GetFingerHandle(i);

            finger.end.x = currentLocation.x;
            finger.end.y = currentLocation.y;
            finger.hasMoved = true;
        }
    }

    touchScreen->RemoveEnded();
}

谢谢!

3 个答案:

答案 0 :(得分:8)

跟踪多个触摸的“正确”方式似乎是UITouch事件的指针值。

您可以在此处的“处理复杂的多点触控序列”部分找到更多详细信息 Apple Developer Documentation

答案 1 :(得分:7)

要修复问题,请删除“handleTouches”方法。你在handleTouches方法中做的第一件事是在touchPhase上切换它,但是已经给你了。如果你接触touchesBegan的触摸,你知道触摸是在UITouchPhaseBegan。通过将四种触摸方法中的触摸汇集到一种方法中,您将失去使用四种委托方法的目的。

在每种方法中,Apple都为您提供了处理当前触摸的不同阶段的机会。

第二件事是您不需要搜索当前触摸的事件,它将作为参数提供给您:触摸。

事件由多组触摸组成。为了方便,您可以获得当前的触摸,即使它也可以在活动中找到。

因此,在touchesBegan中,您开始跟踪触摸。

    - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{


        NSString *startPoint = NSStringFromCGPoint([[touches anyObject] locationInView:self]);  

        NSDictionary * touchData = [NSDictionary dictionaryWithObjectsandKeys: startPoint, @"location", touches, @"touch"]

        [startingLocations addObject:touchData];

        }

我正在使用一系列字典来保存我的触摸数据。

尝试分离您的代码并将其移动到适当的触摸方法中。对于方向,Apple有几个专注于触摸的示例项目,并向您展示如何设置这些方法。

请记住,在每个阶段中,每次触摸都会自动调用这些方法,您无需循环查看事件以了解发生的情况。

指向每组触摸的指针保持不变,只是数据发生变化。

另外,我会阅读关于事件处理的iPhone OS编程指南部分,该部分更深入地介绍了我上面所说的几个图表,解释了触摸与事件之间的关系。

摘录:

  

在iPhone OS中,一个UITouch对象   表示触摸和UIEvent   object代表一个事件。一个事件   对象包含所有触摸对象   目前的多点触控序列和   可以提供特定的触摸对象   视图或窗口(见图3-2)。一个   触摸对象对于给定的持久性   在序列中的手指和UIKit   在跟踪手指时改变它   贯穿始终。触摸属性   这种变化是阶段性的   触摸,它在一个视图中的位置,它   以前的位置及其时间戳。   事件处理代码评估这些   用于确定如何响应的属性   参加活动。

答案 2 :(得分:0)

您应该能够通过存储所有触摸的先前位置来正确整理您的触摸,然后在检测到新触摸时比较这些先前的位置。

-handleTouches方法中,您可以在for循环中输入类似的内容:

// ..existing code..
CGPoint previousLocation = [touch previousLocationInView:self];

// Loop through previous touches
for (int j = 0; j < [previousTouchLocationArray count]; j++) {
  if (previousLocation == [previousTouchLocationArray objectAtIndex:j]) {
    // Current touch matches - retrieve from finger handle j and update position
  }
}

// If touch was not found, create a new Finger and associated entry 

显然,您需要做一些工作才能将其集成到您的代码中,但我非常确定您可以使用这个想法在屏幕上移动时正确识别触摸。另外我只是意识到CGPoint不能很好地适应NSArray - 你需要将它们包装在NSValue对象中(或者使用不同类型的数组)。