Question

I want to get the current object touched in touchesMoved. This is not to be confused with the touchLocation (CGPoint), but the actual object the user is touching. Using UITouch always returns the initial touch (as it says in the apple docs) rather than the current or latest touch.

I have a grid of spots (UIImageViews) that can be 3 by 3 up to 20 by 20.

As the user drags their finger on the screen a line is drawn that tracks the users finger. When a user intersects a gridspot the start point of the line snaps to that spot and continues to track the finger, Essentially allows you to draw shapes on a grid.

Currently i have a for loop that checks if the touchlocation intersects with a grid spot. This does work but is very slow for obvious reasons when their is 400 gridspots.

I have also tried Gesture recognizers but these cancel the touches.

Any help/advice will be much appreciated, thanks!

EDIT: this is what i have in my touchesMoved.

UITouch* touch = [touches anyObject];
CGPoint touchLocation =[touch locationInView:self];

for (int i=100; i<tagInt; i++) {

    UIImageView *img=(UIImageView*)[self.view viewWithTag:i];

    if (CGRectContainsPoint(img.frame, touchLocation)) {
       //Drawing code  setNeedsDisplay etc
    }
 }
Was it helpful?

Solution

As discussed in the comments to the initial question, finding the touch location from the container view seems best. The biggest bottleneck in this code is storing all your objects in one linear array, then checking each element in your array. A better method would be to store the objects in a better format where you can access individual objects based on their position.

If your objects are arranged on a strict grid, then storing them in a two dimensional array should be fast enough. Subdivide your screen into the grid divisions, then find the touchesMoved point within those grid divisions. Use those two integers as indexes to your 2D array, and check the one object available at that location in your array. If you don't have an object at every position on the grid, just store a nil at that location to tell your code "No need to check here". If you may have more than one object at each grid location you can keep a list of the objects at that location in the array, and check all objects in the list. This will be much less than the total (if your objects don't clump up).

Even if your objects are not arranged on a strict grid you can use this technique. Merely dividing your screen into 4 quadrants will reduce the time required to check your objects roughly to one fourth the initial time.

If your objects are moving you'll have to keep this array updated.

This 2D array is just my first thought on a better way of doing this, based on the limited information in your question. It may not be the best way to work in your actual program, and a different data structure and algorithms may be better suited.

OTHER TIPS

You should NOT put drawing code IN the touch handling method. Perhaps the best way is to just save all touch points within a temporary mutable array. And in the drawRect method you draw the correct line once per frame. Take the logic out of the touch handling method. (Also you could make the position fixing calculations in the background, and the line will be updated, after they are finished..)

I still don't quite get what you are trying to draw. could you give us an example image?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top