Mixing NSThreads and NSTimer to update a view

549 Views Asked by At

I want to make an app to make appear and disappear circles on screen. Circles are enlarged on TouchesBegan and smaller on touchesEnd. I'm able to do it on ONE circle but i want to do that everywhere the user touch the screen. I know i have to work with NSThreads, but my example don't work.

This is a piece of my code:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    lastPoint = [touch locationInView:self.view];
    zoomIn = TRUE;
    rayonCercle = 25;

    //Creation d'un thread
    timerThread = [[NSThread alloc] initWithTarget:self selector:@selector(cycle)         object:nil];
    [timerThread start];

    if ([touch tapCount] == 1) {
            NSLog(@"une touche");
    }

    if ([touch tapCount] == 2) {
            drawImage.image = nil;
            return;
    }
}

    - (void) cycle {

        NSLog(@"cycle");

        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
        time = [NSTimer scheduledTimerWithTimeInterval: 0.1
        target: self
        selector: @selector(drawCircle:)
        userInfo: nil
        repeats: YES];

    [runLoop run];
    [pool release];
}

    - (void) drawCircle:(NSTimer *)timer {

            NSLog(@"drawCircle");

            UIGraphicsBeginImageContext(self.view.frame.size);
            [drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width,         self.view.frame.size.height)];


            CGGradientRef myGradient;
            CGColorSpaceRef myColorSpace;
            size_t locationCount = 3;
            CGFloat locationList[] = {0.0, 0.5, 1.0};
            CGFloat colorList[] = {
            1.0, 0.0, 0.5, 1.0, //red, green, blue, alpha
            1.0, 0.0, 1.0, 1.0,
            0.3, 0.5, 1.0, 1.0
            };
            myColorSpace = CGColorSpaceCreateDeviceRGB();
            myGradient = CGGradientCreateWithColorComponents(myColorSpace, colorList,
            locationList, locationCount);

            CGContextDrawRadialGradient(UIGraphicsGetCurrentContext(), myGradient, lastPoint, 0,                 lastPoint,rayonCercle, 0);   

            drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            if (rayonCercle < 200 && zoomIn == TRUE) {
            _hue += 0.5;
            _brightness += 0.005;
            _saturation += 0.05;
            rayonCercle += 15;
            }
            if (zoomIn == FALSE) {
            if (rayonCercle < 0) {
            [time invalidate];
            [timerThread release];
            } else {
            _hue -= 0.5;
            _brightness -= 0.005;
            _saturation -= 0.05;
            rayonCercle -= 1;
            }
    }
}


    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
            UITouch *touch = [touches anyObject];   
            CGPoint currentPoint = [touch locationInView:self.view];
            lastPoint = currentPoint;

            _hue = 0.0;
            _saturation = 0.0;
            _brightness = 0.0;

            rayonCercle = 25;
            zoomIn = TRUE;
    }

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

            _hue = 0.0;
            _saturation = 0.0;
            _brightness = 0.0;

            zoomIn = FALSE;

            UITouch *touch = [touches anyObject];

            if ([touch tapCount] == 2) {
                    drawImage.image = nil;
                    return;
            }
    }
1

There are 1 best solutions below

3
On

you don't need a secondary thread to update the view. just use a delayed callback (NSTimer, targeting the main thread) to invalidate the areas you must draw, and keep track of the position of the nearest touch so you know where to center the drawing. the rect invalidation callbacks will be coalesced using the delayed callback, which is a bonus.