iOS Deployment Target: iOS 9.3, Base SDK: Latest iOS (iOS 11.0), Xcode 9 Beta 4, Swift 4
The following code builds and runs in Swift 3, Xcode 8:
let kern = (CTRunGetAttributes(run) as? [String : Any])?
[NSKernAttributeName] as? CGFloat ?? 0
However, the Swift 4 migrator converts it to this:
let kern = (CTRunGetAttributes(run) as? [String : Any])?
[NSAttributedStringKey.kern] as? CGFloat ?? 0
Xcode 9 now complains:
Cannot subscript a value of type '[String : Any]' with an index of type 'NSAttributedStringKey'
According to the inspector, 'NSAttributedStringKey
' is only available in iOS 11. (Keep in mind that I am targeting iOS 9).
If I replace 'NSAttributedStringKey.kern
' with 'NSKernAttributeName
', the error remains.
Command-clicking on 'NSKernAttributeName
' tells me that its availability is iOS 6. However, the inspector also claims its type is 'NSAttributedStringKey
', which is only available in iOS 11. I do not know if this is merely an artefact of the API presentation, or a stuff-up, or something I'm missing.
Question: how can I use NSKernAttributeName
(or its modernised version) with backward compatibility to iOS 9, with Swift 4?
Thank you for any help.
Type the dictionary as [NSAttributedStringKey : Any] instead of [String : Any]. It's all sugar in the Swift overlay, so it should work even on older macOS/OS X versions.
EDIT: I should clarify my last sentence a bit. NSAttributedStringKey, as well as all the other new "Key" types in Swift 4, exists only in Swift and not in Objective-C. When a dictionary with NSAttributedStringKey keys gets bridged to Objective-C, all the keys will be turned into NSStrings. Since the actual Foundation, UIKit, etc. frameworks you're working with are written in C/Objective-C, this will "just work", and you don't have to worry about the documentation claiming NSAttributedStringKey is 10.11-only.