views:

1985

answers:

2

Fairly common question this, to which I have a few answers and I'm nearly there. I have a button which when pressed, will create an image (code as follows)

(numImages is set on load to ZERO and is used as a count up for the tag numbers of all images created)

UIImage *tmpImage = [[UIImage imageNamed:[NSString stringWithFormat:@"%i.png", sender.tag]] retain];
UIImageView *myImage = [[UIImageView alloc] initWithImage:tmpImage];

numImages += 1;

myImage.userInteractionEnabled = YES;
myImage.tag = numImages;
myImage.opaque = YES;
[self.view addSubview:myImage];
[myImage release];

I then have a touchesBegan method which will detect what's touched. What I need it to do is to allow the user to drag the newly created image. It's nearly working, but the image flickers all over the place when you drag it. I can access the image which you click on as I can get it's TAG, but I just cannot drag it nicely.

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

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view];

    if (touch.view.tag > 0) {
        touch.view.center = location;
    }

    NSLog(@"tag=%@", [NSString stringWithFormat:@"%i", touch.view.tag]);

}

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

It works, in that I get an output of the tag for each image as I click on them. But when I drag, it flashes... any ideas?

A: 

Usually you get an implicit animation when you change center. Are you messing with -contentMode or calling -setNeedsDisplay by any chance?

You can explicitly request animation to avoid the delete and re-draw this way:

if (touch.view.tag > 0) {
    [UIView beginAnimations:@"viewMove" context:touch.view];
    touch.view.center = location;
    [UIView commitAnimations];
}

Do note that NSLog() can be very slow (much slower than you'd expect; it's much more complicated than a simple printf), and that can cause trouble in something called as often as touchesMoved:withEvent:.

BTW, you're leaking tmpImage.

Rob Napier
thanks for the reply. I've tried what you suggested and it still happens. I think it's something to do with the code I am using to set the image? When I place an image on the view in Interface Builder and set that up as an IBOutlet UIImageView in the .h file, that moves around perfectly. Am I missing something when setting up each of my images?? (ps) thanks for the tmpImage tip - missed that one!
Matt Facer
I thought it might have been a problem with the tag.. but now I am thinking it might be an issue with the views. When I place the image using the first bit of code, it goes to 0,0. It always seems to want to move back there when I drag it. So that's causing the flickering. The current position, then it moving back there.... its driving me mad!
Matt Facer
+4  A: 

In answer to my own question - I decided to create a class for handling the images I place on the view.

Code if anyone's interested....

Draggable.h

#import <Foundation/Foundation.h>
@interface Draggable : UIImageView {
    CGPoint startLocation;
}
@end

Draggable.m

#import "Draggable.h"
@implementation Draggable

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
    // Retrieve the touch point
    CGPoint pt = [[touches anyObject] locationInView:self];
    startLocation = pt;
    [[self superview] bringSubviewToFront:self];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
    // Move relative to the original touch point
    CGPoint pt = [[touches anyObject] locationInView:self];
    CGRect frame = [self frame];
    frame.origin.x += pt.x - startLocation.x;
    frame.origin.y += pt.y - startLocation.y;
    [self setFrame:frame];
}
@end

and to call it

UIImage *tmpImage = [[UIImage imageNamed:"test.png"] retain];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tmpImage];

CGRect cellRectangle;
cellRectangle = CGRectMake(0,0,tmpImage.size.width ,tmpImage.size.height );
UIImageView *dragger = [[Draggable alloc] initWithFrame:cellRectangle];
[dragger setImage:tmpImage];
[dragger setUserInteractionEnabled:YES];

[self.view addSubview:dragger];
[imageView release];
[tmpImage release];
Matt Facer
the code above comes from http://www.iphoneexamples.com/
Matt Facer