在 drawRect NSView(macOS 和 ObjC)之上绘制图像(作为叠加层)

Draw image (as an overlay) on top of drawRect NSView (macOS & ObjC)

我在 drawRect 上有一幅我很满意的绘图,我现在正尝试叠加来自特定路径的图像,我希望它作为叠加层继续在当前绘图之上。有谁知道最好的方法是什么,我希望能够设置这张图片的位置和大小。

这可以用核心图形来完成,还是我应该使用 NSImage 来完成这个 - 如果有人能指出正确的方向,我将不胜感激:)

您的 NSView drawRect: 方法可以在 drawRect: 的子类实现之前或之后调用,这使您可以决定其他绘图代码是更早还是更晚执行,从而结束高于或低于 super.

的绘图结果
// in subclass
- (void)drawRect:(CGRect)dirtyrect {
    [super drawRect:dirtyrect];  //to draw super below
    // ask for flip state first
    CGFloat yFlip = self.flipped ? -1.0 : 1.0;
    // your additional
    // drawing code here..
    // and do something with yFlip
    // ...
    //[super drawRect:dirtyrect]; //to draw super on top
}

由于在绘制时可能会考虑视图或图层的 flip 状态,因此您必须在进行自己的绘制调用之前检查翻转状态。为此,要求 self.flippedsuper.flipped 以适应如上所示的视图翻转状态。

但是有很多不同的方法可以将翻转内容与非翻转内容混合使用。
以下代码通过使用 lockFocusFlipped: 方法而不是 lockFocus 方法锁定焦点来创建 NSImage 时遵循 self.flipped 状态。 还展示了其他 API,ps:您不必实现 imageRepresentation,以下包含或多或少的 pseudo 代码

- (NSImage *)imageRepresentation
{
    //BOOL wasHidden = self.isHidden;
    //CGFloat wantedLayer = self.wantsLayer;
    //self.hidden = NO;
    //self.wantsLayer = YES;
    
    NSImage *image = [[NSImage alloc] initWithSize:self.bounds.size];
    
    // to flip an image according to the views flip state
    //[image lockFocus]; 
    [image lockFocusFlipped:self.flipped]; 

    CGContextRef ctx = [NSGraphicsContext currentContext].CGContext;

    // to flip with CoreGraphics API
    //CGContextScaleCTM(ctx, 1.0, -1.0); // <-- see -1.0?
    //CGContextTranslateCTM(ctx, 1.0, 1.0);
    
    // or Affine Transform API, pseudo code
    //NSAffineTransform *trans = [NSAffineTransform transform];
    //[trans translateXBy:0 yBy:existingSize.height];
    //[trans scaleXBy:1 yBy:-1];
    //[trans concat];
    //[image drawAtPoint:NSZeroPoint fromRect:NSMakeRect(0, 0, newSize.width, newSize.height) operation:NSCompositingOperationSourceOver fraction:1.0];

    //[self.layer renderInContext:ctx]; // <-- CALayer backed view drawing

    [self drawRect:self.bounds.size]; // <-- classic View drawing

    [image unlockFocus];

    //self.wantsLayer = wantedLayer;
    //self.hidden = wasHidden;
    return image;
}