6

I have the following code in my project in Xcode 8.3.3 (Swift 3.1):

let font = CGFont(provider!) CTFontManagerRegisterGraphicsFont(font, &error) 

But in Xcode 9 Beta (Swift 4), I get the following error:

Value of optional type 'CGFont?' not unwrapped; did you mean to use '!' or '?'?

The error is because the initializer for CGFont that takes a CGDataProvider now returns an optional.

But when I apply the fix of:

let font = CGFont(provider) CTFontManagerRegisterGraphicsFont(font!, &error) 

The code no longer compiles in Xcode 8.3.3 with Swift 3.1 since font is not an optional and thus doesn't play nicely with the !.

Is there a way to make this work in both versions of Xcode? Is Swift 4 supposed to be backwards compatible (compile with Swift 3 compiler)?

1
  • I'd say this is a breaking change in Core Graphics (initializer has become failable), so it has nothing to do with Swift 4. But I think you could use conditional compilation to work around this problem. Commented Jun 20, 2017 at 21:35

2 Answers 2

7

This is a breaking change in Core Graphics not in Swift itself. API has changed, the initializer is now failable.

Use conditional compilation to make your code compile with both 3.1 and 4.0 compiler:

#if swift(>=4.0) let font = CGFont(provider!) #else let font = CGFont(provider)! #endif CTFontManagerRegisterGraphicsFont(font, &error) 
Sign up to request clarification or add additional context in comments.

2 Comments

If I use this then I noticed even in Xcode 9 I was hitting the 'else' case. So I went to my project settings and changed Swift Language Version to Swift 4.0. But now again if I open in Xcode 8 then it complains about an unsupported swift version...
@AdamJohns Perhaps the problem is that the new compiler is still in beta, so it might have a version like 4.0.beta... Try changing the version in the conditional compilation statement to 3.3 (or other nonexistent 3.x version). Or, to avoid guessing, run swiftc --version as one of the build phase scripts to see the exact version of Swift compiler in Xcode 9 and 8.3. Maybe Xcode 9 uses the older version of command line tools (check Locations tab in Xcode settings).
4

I ended up using the following method which allowed for backwards compatibility without conditional compilation (idea taken from this blog post):

func optionalize<T>(_ x: T?) -> T? { return x } 

This way in both Xcode 8 and Xcode 9 I could use:

guard let font = optionalize(CGFont(provider)) else { return } CTFontManagerRegisterGraphicsFont(font, &error) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.