Swift 4 Conversion Error - NSAttributedStringKey: Any

I recently converted my application and I continue to receive an error message

"Cannot convert value of type '[String: Any]' to expected type of argument '[NSAttributedStringKey: Any]?'

barButtonItem.setTitleTextAttributes(attributes, for: .normal)

All code:

  class func getBarButtonItem(title:String) -> UIBarButtonItem { let barButtonItem = UIBarButtonItem.init(title: title, style: .plain, target: nil, action: nil) let attributes = [NSAttributedStringKey.font.rawValue: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor: UIColor.white] as! [String : Any] barButtonItem.setTitleTextAttributes(attributes, for: .normal) return barButtonItem } 
+27
swift4
source share
4 answers

Why did you get this error

Previously, your attributes defined as [String: Any] , where the key is taken from NSAttributedStringKey as a string or NSAttributedString.Key in Swift 4.2.

During migration, the compiler tries to save the type [String: Any] . However, NSAttributedStringKey becomes a structure in swift 4. Thus, the compiler tries to change this to a string, getting its raw value.

In this case, setTitleTextAttributes looks for [NSAttributedStringKey: Any] but you [NSAttributedStringKey: Any] [String: Any]

To fix this error:

Remove .rawValue and .rawValue your attributes as [NSAttributedStringKey: Any]

Namely, change the following line

 let attributes = [NSAttributedStringKey.font.rawValue: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor: UIColor.white] as! [String : Any] 

in

 let attributes = [NSAttributedStringKey.font: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor: UIColor.white] as! [NSAttributedStringKey: Any] 

And in Swift 4.2,

  let attributes = [NSAttributedString.Key.font: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedString.Key.foregroundColor: UIColor.white] as! [NSAttributedStringKey: Any] 
+44
source share

NSAttributedStringKey ( NSAttributedStringKey.font ) is expected and you send String ( NSAttributedStringKey.font.rawValue ).

So, replace NSAttributedStringKey.font.rawValue with NSAttributedStringKey.font , as shown below:

 let attributes = [NSAttributedStringKey.font: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor: UIColor.white] 
+15
source share

As noted in previous answers, NSAttributedStringKey was restructured in Swift 4. However, other objects that use NSAttributedStringKey did not appear to be updated at the same time.

The simplest fix without changing any other code is to add .rawValue to all setters in the NSAttributedStringKey set - turn the key names into String s:

 let attributes = [ NSAttributedStringKey.font.rawValue: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor.rawValue: UIColor.white ] as [String : Any] 

Please note that now you do not need ! in as .

Alternatively, you can skip the as cast at the end by declaring an array of [String : Any] upfront:

 let attributes: [String : Any] = [ NSAttributedStringKey.font.rawValue: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor.rawValue: UIColor.white ] 

Of course, you need to add .rawValue for each NSAttributedStringKey element that you set.

+5
source share

The linear answer is correct for cases where you still need to use [String: Any] and not [NSAttributedStringKey: Any] .

For example, in UIKit, UITextView.typingAttributes is still of type [String: Any] . Thus, for this property you must use the converted attributes (including custom ones):

 let customAttributeName = "MyCustomAttributeName" let customValue: CGFloat = 15.0 let normalTextAttributes: [NSAttributedStringKey : Any] = [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 14.0), NSAttributedStringKey.foregroundColor : UIColor.blue, NSAttributedStringKey.backgroundColor : UIColor.clear, NSAttributedStringKey(rawValue: customAttributeName): customValue] textView.typingAttributes = normalTextAttributes.toTypingAttributes() 

where toTypingAttributes() is a function defined by the extension in any of your project files:

 extension Dictionary where Key == NSAttributedStringKey { func toTypingAttributes() -> [String: Any] { var convertedDictionary = [String: Any]() for (key, value) in self { convertedDictionary[key.rawValue] = value } return convertedDictionary } 
+2
source share

All Articles