Question

In an single view iPhone app I have the following structure: scrollView -> contentView -> imageView and underneath (at the main view) there are 7 draggable custom views - which can be dragged from/to the contenView.

Initially dragging was handled in the custom views (see Tile.m@2eb672523a) and while this worked well it required sending notifications to the main view.

So I'm trying to move touchesBegan and friends to the main app view (see ViewController.m).

My problem is:

Initially I had this code in the contentView (see GameBoard.m) to enable subview dragging at the scrollView:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    return result == self ? nil : result;
}

However when trying to drag a tile back from contentView to the main view (in the direction shown in the below screenshot) this wouldn't deliver touchesBegan to the main view.

app screenshot

So I have changed this method to return the main view instead of the tiles:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    return result == self ? nil : self.window.rootViewController.view;
}

Now touchesBegan is called on the main view (as I can see in the debugger), but the touches.view is pointing to the main view too.

My question is:

How to find the touched tile in the new touchesBegan method?

Was it helpful?

Solution

Nevermind, I've solved my problem.

In ViewController.m I've added a _draggedTile ivar and set it in touchesBegan by using the following method to find the touched tile:

- (SmallTile*) findTileAtPoint:(CGPoint)point withEvent:(UIEvent*)event
{
    NSArray* children = [self.view.subviews arrayByAddingObjectsFromArray:_contentView.subviews];

    for (UIView* child in children) {
        CGPoint localPoint = [child convertPoint:point fromView:self.view];

        if ([child isKindOfClass:[SmallTile class]] &&
            [child pointInside:localPoint withEvent:event]) {
            return (SmallTile*)child;
        }
    }

    return nil;
}

And in touchedMoved, touchesEnded, touchesCancelled I just use that ivar (initially I was using the above findTileAtPoint:withEvent: method there as well, but sometimes the touch wouldn't be exactly over the dragged tile and the movement was jerky or cancelled).

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