Swift 4 has a new NSRect.fill() function to replace NSRectFill(). When attempting to clear a bitmap using NSColor.clear.setFill(), the bitmap remains unchanged using NSRect.fill().
A workaround is to use NSRect.fill(using:) and specifying .copy.
Here is what the code does in Playgrounds in Swift 4:
Sample code:
// Duplicating a bug with Xcode 9 and Swift 4
import Cocoa
var image = NSImage(size: NSSize(width: 32, height: 32))
let rect = NSRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
image.lockFocus()
NSColor.red.setFill()
rect.fill()
image.unlockFocus()
image.lockFocus()
NSColor.clear.setFill()
// calling fill() with a clear color does not work
rect.fill()
image.unlockFocus()
// Image above should not be red
image.lockFocus()
NSColor.clear.setFill()
// using fill(using:) does work
rect.fill(using: .copy)
image.unlockFocus()
// image above is properly cleared
Is this a bug that I should file with Apple or am I missing something? This sequence worked in Swift 3 using NSRectFill().
They have simply different default logic:
Old syntax was always .copy.
New syntax is context if present or .sourceOver.
(source: https://developer.apple.com/documentation/appkit/1473652-nsrectfill)
(source: Xcode comments for https://developer.apple.com/documentation/corefoundation/cgrect/2903486-fill/)
So if you're converting old code to newer format, then
rect.fill(using: .copy)
is the syntax to keep identical behaviour.