2

I have an NSView with a drawRect

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSPoint origin = [self visibleRect].origin;
    [[NSGraphicsContext currentContext]
     setPatternPhase:NSMakePoint(origin.x, origin.y)];
    [[NSColor colorWithPatternImage: self.image] set];
    [NSBezierPath fillRect: [self bounds]];
}

It draws my pattern perfectly, but i can see the pattern scroll when i change the the size of my window.

i have tried to set the view isFlipped to YES but that doesn't change anything.

Andy Jacobs
  • 15,187
  • 13
  • 60
  • 91

2 Answers2

1

You need to do some off-screen drawing first and then draw that result onto the view. For example you can use a blank NSImage of the exact same size as the view, draw the pattern on that image and then draw that image on the view.

Your code may look something like that:

- (void)drawRect:(NSRect)dirtyRect
{
  // call super
  [super drawRect:dirtyRect];

  // create blank image and lock drawing on it    
  NSImage* bigImage = [[[NSImage alloc] initWithSize:self.bounds.size] autorelease];
  [bigImage lockFocus];

  // draw your image patter on the new blank image
  NSColor* backgroundColor = [NSColor colorWithPatternImage:bgImage];
  [backgroundColor set];
  NSRectFill(self.bounds);

  [bigImage unlockFocus];

  // draw your new image    
  [bigImage drawInRect:self.bounds
            fromRect:NSZeroRect 
           operation:NSCompositeSourceOver 
            fraction:1.0f];
}

// I think you may also need to flip your view
- (BOOL)isFlipped
{
  return YES;
}
Neovibrant
  • 747
  • 8
  • 16
0

Swift

A lot has changed, now things are easier, unfortunately part of objective-C's patrimony is lost and when it comes to Cocoa, Swift is like an orphan child. Anyways, based on Neovibrant's we can deduct the solution.

  1. Subclass NSView
  2. Override draw method
    • Call parent method (this is important)
    • Set a fill on buffer within the bounds of the view
    • Draw fill on buffer

code

    override func draw(_ dirtyRect: NSRect) {
         super.draw(dirtyRect)

         let bgimage : NSImage = /* Set the image you want */
         let background = NSColor.init(patternImage: bgimage)
         background.setFill()

         bgimage.draw(in: self.bounds, from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
    }
yeyo
  • 2,954
  • 2
  • 29
  • 40