How to cast a UIFont object to CTFont in Swift
Asked Answered
M

2

13

I'm trying to port some code to Swift that uses UIFont and CTFont, and that (successfully, in Objective-C) uses simple bridged casts to get from one to the other and vice versa.

For example, consider this code (in a UIFontDescriptor category):

UIFont *font = [UIFont fontWithDescriptor:self size:0.0];
NSArray *features = CFBridgingRelease(CTFontCopyFeatures((__bridge CTFontRef)font));

I haven't yet been able to figure out how to express this in Swift in a way that will actually compile. The following at least doesn't:

let font = UIFont(descriptor:self, size: 0.0)
let features = CTFontCopyFeatures(font as CTFont)

Error: 'UIFont' is not convertible to 'CTFont'

Macegan answered 27/6, 2014 at 16:40 Comment(1)
Well I don't know if that works but you could maybe try to initialize the UIFontas AnyObjectand then cast it to CTFont. I think at least the casting should work as every class inherits from AnyObject.Cologne
M
2

This has apparently been fixed in a later version of Swift and/or CoreText. At least it works now in my testing using Xcode 7.0.1.

Macegan answered 7/10, 2015 at 14:11 Comment(0)
R
2

Try this. You can't just coerce the values from one type to another. If you create a CTFont from the descriptor and size though, it seems to give you a valid array even if you don't include a matrix for transformations (the nil parameter)

let font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nil)
let features: NSArray = CTFontCopyFeatures(font)

As for creating the CTFontDescriptor, I'd use CTFontDescriptorCreateWithNameAndSize or CTFontDescriptorCreateWithAttributes depending on what you're originally given. The latter takes a simple NSDictionary, and the former just uses a font name and size.

To go from an existing font (call it originalFont) just do the following to get a descriptor:

let font = CTFontCreateWithName(originalFont.fontName as CFStringRef, 
    originalFont.pointSize as CGFloat, nil)
Rus answered 27/6, 2014 at 17:3 Comment(3)
While that should certainly work, I'm really looking for a way to go from an existing UIFont instance to CTFont without recreating it from scratch. This should really be possible considering that “its reference type, CTFontRef, is toll-free bridged with UIFont in iOS and NSFont in OS X”, according to the docsMacegan
That's still creating a new font object, just using the data from the original one. I think it should somehow be possible to do the equivalent to the Objective-C toll-free bridged cast in Swift. Maybe the Core Text API just hasn't been annotated/modernized yet to allow this.Macegan
@dylan gattey : I suggest changing the casting of the originalFont.pointSize from CFStringRef to CGFloat as it is currently incorrectly casted.Neper
M
2

This has apparently been fixed in a later version of Swift and/or CoreText. At least it works now in my testing using Xcode 7.0.1.

Macegan answered 7/10, 2015 at 14:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.