A few months back I wrote a fairly simple Swift command line app in Xcode. The app did some Core Graphics drawing and saved the results to a PDF in the user’s Documents directory. The project consisted of a single main.swift
file. Running it from with Xcode worked great. The PDF was created and saved to disk.
Today, I tried running either the uncompiled main.swift
file or the compiled command line app from the command line with the following results:
$ ./main.swift
./main.swift:102:27: error: 'init(CGContext:flipped:)' is only available on OS X 10.10 or newer
let graphicsContext = NSGraphicsContext(CGContext: context!, flipped:false)
^
./main.swift:102:27: note: add 'if #available' version check
let graphicsContext = NSGraphicsContext(CGContext: context!, flipped:false)
^
./main.swift:102:27: note: add @available attribute to enclosing global function
let graphicsContext = NSGraphicsContext(CGContext: context!, flipped:false)
^
Even though I’m running this on OS X 10.11 and even though this runs just fine from within Xcode, it’s complaining that I’m trying to use a bit of API that might not be available.
Solution #1
The app kicks off by calling a function called drawPDF()
. It’s within that function that the call to NSGraphicsContext(CGContext: context!, flipped:false)
is made. So the first way to get this to work is to make sure the offending code isn’t executed on a pre-10.10 system. In this case, I’ll use a guard
statement at the top of the function that will skip the entire function if the user isn’t on 10.10 or newer:
func drawPDF() {
guard #available(OSX 10.10, *) else {return}
// ... the rest of the function ...
This allows the file to be run from the command line, but then Xcode flags that line with a warning: Unnecessary check for 'OSX'; minimum deployment target ensures guard will always be true
. Yes, my Xcode project requires at least OS X 10.11, so Xcode is pointing out that I don’t need this check because we are guaranteed to always be running at OS 10.11. That’s a little annoying and I’m sure there’s a project setting to silence this kind of warning. But I’m not a big fan of silencing warnings. So this is an imperfect solution.
Solution #2
Add a @available
attribute on the function that makes the potentially problematic API:
@available (OSX 10.10, *)
func drawPDF() {
// ... the rest of the function ...
This doesn’t quite work because running from the command line now complains that I’m calling drawPDF()
and that function requires at least OS X 10.10. So I have to do an if #available
check before calling it:
if #available(OSX 10.10, *) {
drawPDF()
}
And with that, it works great at the command line, but I get another one of those warning from Xcode telling me that I’m doing an unnecessary #available
check.
Conclusion
I’m not sure what the best/correct solution is. These both work but I don’t like the warnings in Xcode. ¯\_(ツ)_/¯