I converted my app recently and I keep getting the error
"Cannot convert value of type '[String : Any]' to expected argument type '[NSAttributedStringKey: Any]?'
barButtonItem.setTitleTextAttributes(attributes, for: .normal)
Whole 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
}
Previously, your attributes
is defined as [String: Any]
, where the key comes from NSAttributedStringKey
as a string or NSAttributedString.Key
in Swift 4.2
During the migration, the compiler tries to keep the [String: Any]
type. However, NSAttributedStringKey
becomes a struct in swift 4. So the compiler tries to change that to string by getting its raw value.
In this case, setTitleTextAttributes
is looking for [NSAttributedStringKey: Any]
but you provided [String: Any]
Remove .rawValue
and cast your attributes
as [NSAttributedStringKey: Any]
Namely, change this following line
let attributes = [NSAttributedStringKey.font.rawValue:
UIFont(name: "Helvetica-Bold", size: 15.0)!,
NSAttributedStringKey.foregroundColor: UIColor.white] as! [String : Any]
to
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]
Its expecting NSAttributedStringKey
(NSAttributedStringKey.font
) and you are sending String
(NSAttributedStringKey.font.rawValue
).
So please replace NSAttributedStringKey.font.rawValue
with NSAttributedStringKey.font
like below :
let attributes = [NSAttributedStringKey.font: UIFont(name: "Helvetica-Bold", size: 15.0)!, NSAttributedStringKey.foregroundColor: UIColor.white]
As noted in previous answers, NSAttributedStringKey
was changed to a struct in Swift 4. However, other objects that use NSAttributedStringKey
apparently didn't get updated at the same time.
The easiest fix, without having to change any of your other code, is to append .rawValue
to all your occurrences of NSAttributedStringKey
setters - turning 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]
Note that you won't need the !
at the as
now, either.
Alternatively, you can skip the as
cast at the end by declaring the array to be [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 still need to append the .rawValue
for each NSAttributedStringKey
item you set.
leanne's answer is correct for the 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]
. So for that property you have to use 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 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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With