Swift 4 - Xcode 9 beta 4 - NSKernAttributeName vs NSAttributedStringKey

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. (Note that I'm targeting iOS 9).

If I replace ' NSAttributedStringKey.kern

with NSKernAttributeName

', the error remains.

By clicking on the " NSKernAttributeName

" button , I am told that its availability is iOS 6. However, the inspector also claims that its type is " NSAttributedStringKey

", which is only available in iOS 11. I don't know if it's just an API view artifact or stuffing or something. what I am missing.

Question: How can I use NSKernAttributeName

(or an upgraded version of it) backward compatible with iOS 9 with Swift 4?

Thanks for any help.

+3


source to share


3 answers


Enter the dictionary as [NSAttributedStringKey: Any] instead of [String: Any]. These are all sugar in the Swift layer, so it should work even on older versions of macOS / OS X.



EDIT: I have to clarify the last sentence a bit. NSAttributedStringKey as well as all the other new "key" types in Swift 4 only exist in Swift, not Objective-C. When a dictionary with NSAttributedStringKey is connected to Objective-C, all keys will be converted to NSStrings. Since the actual Foundation, UIKit, etc. frameworks you are working with are written in C / Objective-C, this will โ€œjust workโ€ and you donโ€™t have to worry about documentation requiring the NSAttributedStringKey to be 10.11.

+8


source


Swift 4

If you don't want to ignore the warning and bring whatever, you can copy them completely into the new dictionary.



var attributes: [NSAttributedStringKey: Any] = [:]
textField.defaultTextAttributes.forEach{
    attributes[NSAttributedStringKey(rawValue: $0.key)] = $0.value
}

      

+1


source


textField.defaultTextAttributes[NSAttributedStringKey.kern.rawValue] = 16

      

0


source







All Articles