macoscocoaaffinetransformnsaffinetransform

Apply NSAffineTransform to NSView


I want to do a couple of simple transforms on an NSView subclass to flip it on the X axis, the Y axis, or both. I am an experienced iOS developer but I just can't figure out how to do this in macOS. I have created an NSAffineTransform with the required translations and scales, but cannot determine how to actually apply this to the NSView. The only property I can find which will accept any kind of transform is [[NSView layer] transform], but this requires a CATransform3D.

The only success I have had is using the transform to flip the image if an NSImageView, by calling lockFocus on a new, empty NSImage, creating the transform, then drawing the unflipped image inside the locked image. This is far from satisfactory however, as it does not handle any subviews and is presumably more costly than applying the transform directly to the NSView/NSImageView.


Solution

  • This was the solution:

    - (void)setXScaleFactor:(CGFloat)xScaleFactor {
        _xScaleFactor = xScaleFactor;
        [self setNeedsDisplay];
    }
    
    - (void)setYScaleFactor:(CGFloat)yScaleFactor {
        _yScaleFactor = yScaleFactor;
        [self setNeedsDisplay];
    }
    
    - (void)drawRect:(NSRect)dirtyRect {
        NSAffineTransform *transform = [[NSAffineTransform alloc] init];
        [transform scaleXBy:self.xScaleFactor yBy:self.yScaleFactor];
        [transform set];
    
        [super drawRect:dirtyRect];
    }
    

    Thank you to l'L'l for the hint about using NSGraphicsContext.