1

how to remove subviews very fast according to user touched point or moving point in the view.I am able to get the user touched point and moved point in the view and also i can remove the subview according with the user touched point using [subview removefromsuperview];.

When the user moves very fast some subviews getting deleted and some of the images not getting deleted.If the user moves slowly then subviews getting deleted exactly.i am placing some of my code is below

`

-(void)deleteSubView:(CGPoint)userCurrentPoint{

 for(int i=0;i<[subviews count];i++){

if (CGRectContainsPoint([[subviews objectAtIndex:i] CGRectValue], userCurrentPoint)) {

                [[superview viewWithTag:i ] removeFromSuperview];



    }
}

`

is there any way to delete subviews according with the user fast moving points.i need your suggestion. Thanks all

ajay
  • 3,245
  • 4
  • 31
  • 59

3 Answers3

2

Put this in your header file:

@interface YourView : UIView

@property (nonatomic, assign) CGPoint lastTouchLocation;
@end

This should be the implementation:

@implementation YourView
@synthesize lastTouchLocation;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];

    self.lastTouchLocation = [[touches anyObject] locationInView:self];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    CGPoint oldLocation = self.lastTouchLocation;
    CGPoint newLocation = [[touches anyObject] locationInView:self];

    for (UIView *subview in self.subviews)
    {
        if (LineIntersectsRect(oldLocation, newLocation, subview.frame))
        {
            [subview removeFromSuperview];
        }
    }

    self.lastTouchLocation = newLocation;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    self.lastTouchLocation = CGPointZero;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];

    self.lastTouchLocation = CGPointZero;
}
@end

What this does: we check whether or not a line between the last received touch and the current one intersects the frame of a subview. Why? See deanWombourne's answer.

Here's the intersection code, originally by habjan - you should put in in the header, too.

static inline BOOL LineIntersectsLine(CGPoint l1p1, CGPoint l1p2, CGPoint l2p1, CGPoint l2p2)
{
    CGFloat q = (l1p1.y - l2p1.y) * (l2p2.x - l2p1.x) - (l1p1.x - l2p1.x) * (l2p2.y - l2p1.y);
    CGFloat d = (l1p2.x - l1p1.x) * (l2p2.y - l2p1.y) - (l1p2.y - l1p1.y) * (l2p2.x - l2p1.x);

    if(d == 0)
    {
        return false;
    }

    CGFloat r = (q / d);
    q = (l1p1.y - l2p1.y) * (l1p2.x - l1p1.x) - (l1p1.x - l2p1.x) * (l1p2.y - l1p1.y);

    CGFloat s = (q / d);

    if((r < 0) || (r > 1) || (s < 0) || (s > 1))
    {
        return false;
    }
    else
    {
        return true;
    }
}

static inline BOOL LineIntersectsRect(CGPoint p1, CGPoint p2, CGRect r)
{
    if (CGRectContainsPoint(r, p1) || CGRectContainsPoint(r, p2))
    {
        return YES;
    }
    else
    {
        CGPoint topLeft = CGPointMake(r.origin.x, r.origin.y);
        CGPoint topRight = CGPointMake(r.origin.x + r.size.width, r.origin.y);
        CGPoint bottomLeft = CGPointMake(r.origin.x, r.origin.y + r.size.height);
        CGPoint bottomRight = CGPointMake(r.origin.x + r.size.width, r.origin.y + r.size.height);

        return (LineIntersectsLine(p1, p2, topLeft, topRight) ||
                LineIntersectsLine(p1, p2, topRight, bottomRight) ||
                LineIntersectsLine(p1, p2, bottomRight, bottomLeft) ||
                LineIntersectsLine(p1, p2, bottomLeft, topLeft));
    }
}
Community
  • 1
  • 1
Christian Schnorr
  • 10,768
  • 8
  • 48
  • 83
1

It's not to do with your enumeration :)

If the user moves their finger quickly, you don't get a list of every pixel they touched, you get some of them. If they were to move fast enough, you might only get the start and end points.

You can't just use the point that their finger is dragged to, you have to work out which subviews have been touched between the last event and this one :)

Think of it as drawing a line between the start and end points and working out which subviews overlap with that line.

deanWombourne
  • 38,189
  • 13
  • 98
  • 110
0

If I understand your question correctly, you want to remove all the subviews that the user touches as he drags his finger across your view.

Your problem is that touchesMoved:withEvent: fires at a limited frequency. It isn't guaranteed to fire for every pixel the user touches. As a result, when the user moves his finger quickly, there are gaps between the points reported in touchesMoved:withEvent. If the user moves his finger quickly enough, these gaps may be large enough that they skip over some subviews entirely.

To solve this problem your code needs to remember the position of the previous point, and then test the line segment formed by the previous point and the current point to see if it intersects with the frame of the subview. An efficient algorithm for this is described in: How to test if a line segment intersects an axis-aligned rectange in 2D?

Community
  • 1
  • 1
cduhn
  • 17,818
  • 4
  • 49
  • 65