SetNeedsDisplayInRect: only creates a white rectangle

I'm still a little fresh for CoreGraphics programming, so please bear with me. I am trying to write an application that allows the user to wipe the image with his finger. I have basic functionality nailed down, but the result is sluggish, as the screen is completely redrawn every time I click. I did some research and found out that I can only update part of the screen using the UIView setNeedsDisplayInRect: method.

This calls drawRect: as expected, however everything I draw in drawRect: after setNeedsDisplayInRect: is ignored. Instead, the area in the direct parameter is simply filled with white. No matter what I draw inside, all I get is a white rectangle.

In essence, this is what I am doing:

1) when the user touches the screen, this touch is displayed in the mask 2) when drawRect is called: the image is masked using this mask

Must be something simple, I certainly don’t notice?

+3
source share
2 answers

I found a solution, but I still manage to avoid how this works. Here is the code:

This method flips the given rectangle in the same way that the coordinate transformation in the context flips the context coordinate system:

- (CGRect) flippedRect:(CGRect)rect
{
    CGRect flippedRect = rect;

    flippedRect.origin.y = self.bounds.size.height - rect.origin.y - rect.size.height;

    return CGRectIntersection( self.bounds, flippedRect );
}

This computes the rectangle to be updated from the touch location. Note that the rectangle is upside down:

- (CGRect) updateRectFromTouch:(UITouch *)touch
{
    CGPoint location = [touch locationInView:self];

    int d = RubbingSize;

    CGRect touchRect = [self flippedRect:CGRectMake( location.x - d, location.y - d, 2*d, 2*d )];

    return CGRectIntersection( self.frame, touchRect );
}

When rendering, tap the rectangles with the 'flipped' update:

- (void) renderTouch:(UITouch *)touch
{
    //
    // Code to render into the mask here
    //

    if ( m_updateRect.size.width == 0 )
    {
        m_updateRect = [self updateRectFromTouch:touch];
    }
    else 
    {
        m_updateRect = CGRectUnion( m_updateRect, [self updateRectFromTouch:touch] );
    }
}   

20 . 1/20 :

- (void) refreshScreen
{
    if ( m_updateRect.size.width > 0 )
    {
        [self setNeedsDisplayInRect:[self flippedRect:m_updateRect]];
    }
}

:

BOOL rectIsEqualTo(CGRect a, CGRect b)
{
    return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height;
}

drawRect: , .

- (void)drawRect:(CGRect)rect 
{
    BOOL drawFullScreen = rectIsEqualTo( rect, self.frame );

    // Drawing code

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Turn coordinate system around

    CGContextTranslateCTM( context, 0.0, self.frame.size.height );

    CGContextScaleCTM( context, 1.0, -1.0 );

    if ( drawFullScreen )
    {
        // draw the full thing
        CGContextDrawImage( context, self.frame, self.image );
    }
    else 
    {       
        CGImageRef partialImage = CGImageCreateWithImageInRect( self.image, [self flippedRect:m_updateRect] );

        CGContextDrawImage( context, m_updateRect, partialPhoto );

        CGImageRelease( partialImage );
    }

        ...

    // Reset update box

    m_updateRect = CGRectZero;
}

- , , .

+2

, , , UIKit "" Core Graphics.

Apple

+1

Source: https://habr.com/ru/post/1739991/


All Articles