17

just started swift 3 and I have problems with swift syntax.

i'm trying to display a simple NSAttributedString.

so 1st I set my attributes :

let attributeFontSaySomething : [String : AnyObject] = [NSFontAttributeName : UIFont.fontSaySomething()]
let attributeColorSaySomething : [String : AnyObject] = [NSForegroundColorAttributeName : UIColor.blue]

Then I create my string :

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: self.attributeFontSaySomething)

What i would like to do is to create the string with my 2 attributes not only just one. But when i do :

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: [self.attributeFontSaySomething, self.attributeColorSaySomething])

Xcode tells me I can't and want me to change this for a literal dictionary.

How can I create my string with the 2 attributes without using a NSMutableAttributedString ?

Bhavin Ramani
  • 3,221
  • 5
  • 30
  • 41
user2206906
  • 1,310
  • 2
  • 13
  • 18

8 Answers8

26

The main issue is that you are passing an array [attr.. , attr...] rather than one dictionary.

You need to merge the two dictionaries into one

let attributeFontSaySomething : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12.0)]
let attributeColorSaySomething : [String : Any] = [NSForegroundColorAttributeName : UIColor.blue]

var attributes = attributeFontSaySomething
for (key, value) in attributeColorSaySomething {
    attributes(value, forKey: key)
}

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: attributes)

However it might be easier to create the dictionary literally:

let attributes : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12.0), NSForegroundColorAttributeName : UIColor.blue]
vadian
  • 274,689
  • 30
  • 353
  • 361
7

Just create a single dictionary with both sets of attributes:

let attributes: [String:AnyObject] = 
  [NSFontAttributeName : UIFont.fontSaySomething(), 
  NSForegroundColorAttributeName : UIColor.blue]

And then use the dictionary with both key/value pairs when creating your attributed string.

There's no built-in mechanism in Swift for combining dictionaries, but you could add an override of the + operator if you wanted to be able to add dictionaries together (You'd have to work out what to do if both dictionaries contained the same key however.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Could I ask to check for Swift 4.0 version? I first tried to make [NSAttributedStringKey: AnyObject] array, but I cannot use any NSAttribute...Name. – Drwalcore Sep 13 '17 at 16:26
3

Thanks for @vadian's answer

Update For Swift 4

let attributes : [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 12.0), NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue) : UIColor(hex:"4C0000")]

refreshControl.attributedTitle=NSAttributedString(string: "Refreshing...", attributes: attributes)
Baljeet Singh
  • 453
  • 5
  • 15
  • You are taking an `NSAttributedStringKey`, converting it into a `String`, and then using that `String` to construct an `NSAttributedStringKey`. There is no need for that at all. Just use the `NSAttributedStringKey`. In fact, you can just use `.font` instead of `NSAttributedStringKey.font`. – Software2 May 30 '18 at 21:01
2

Use like this:

let attStringSaySomething = NSAttributedString.init(string: "Hello", attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 16), NSForegroundColorAttributeName:UIColor.black])
Poles
  • 3,585
  • 9
  • 43
  • 91
2

You can use this code for different attributes on different strings With Roboto font (For Roboto font use MDFRobotoFontLoader)

let yourAttributes = [NSForegroundColorAttributeName: UIColor.black, NSFontAttributeName: MDFRobotoFontLoader.sharedInstance().regularFont(ofSize: 20)]

let finalString =  NSMutableAttributedString(string: "", attributes: yourAttributes)

let attributeStr =  NSMutableAttributedString(string: "XYZGFDGii", attributes: yourAttributes)
       finalString.append(attributeStr)

let yourOtherAttributes = [NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: MDFRobotoFontLoader.sharedInstance().regularFont(ofSize: 24)]

let partTwo = NSMutableAttributedString(string: "hfjghlkdhkjld", attributes: yourOtherAttributes)
       finalString.append(partTwo)

This example uses Roboto font

Ashwini Chougale
  • 1,093
  • 10
  • 26
DURGESH
  • 2,373
  • 1
  • 15
  • 13
0

The problem is that you are inserting two dictionaries into a dictionary, what only expects [String: Any], not [[String: Any], [String: Any]] type. You can do the following:

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: [NSFontAttributeName : UIFont.fontSaySomething(), NSForegroundColorAttributeName : UIColor.blue])

You could also group the values into tuples instead of dictionaries, and insert them into your dictionary based on the key and value:

let attributeFontSaySomething = (key: NSFontAttributeName, value: UIFont.fontSaySomething())
let attributeColorSaySomething = (key: NSForegroundColorAttributeName, value: UIColor.blue)

let attStringSaySomething = NSAttributedString(string: "Say something", attributes: [attributeFontSaySomething.key : attributeFontSaySomething.value,attributeColorSaySomething.key : attributeColorSaySomething.value])
dirtydanee
  • 6,081
  • 2
  • 27
  • 43
0

Some of the answers are out dated here, especially for Swift 4 and above, you can use something like:

let wholeString = "This is whole string"
let partToAttribute = "whole string"

let attributedMessage = NSMutableAttributedString(string: wholeString)
    .highlightString(with: UIColor.blue, for: partToAttribute, isBackground: true)
    .fontHighlightString(with: UIFont.makeBoldFont(size: 16), color: UIColor.white, for: partToAttribute)

titleLabel.attributedText = attributedMessage

So at the end, you apply 2 attributes which are highlightString and fontHighlightString

Umit Kaya
  • 5,771
  • 3
  • 38
  • 52
0

First you can initialise attributes by using

var myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.init(hexString: "#FFAEA9"), NSAttributedString.Key.font: UIFont(name: "Dubai-Medium", size: 16) ]

after that you can use it...

  let myString = "Enter default amount"
            let text = NSAttributedString(string: myString, attributes: myAttribute)
            enterCustomAmount.setAttributedTitle(text, for: .normal)
Moeez Ali
  • 11
  • 2