fonts - How do I make an attributed string using Swift? -
i trying make simple coffee calculator. need display amount of coffee in grams. "g" symbol grams needs attached uilabel using display amount. numbers in uilabel changing dynamically user input fine, need add lower case "g" on end of string formatted differently updating numbers. "g" needs attached numbers number size , position changes, "g" "moves" numbers. i'm sure problem has been solved before link in right direction helpful i've googled little heart out.
i've searched through documentation attributed string , downloded "attributed string creator" app store, resulting code in objective-c , using swift. awesome, , helpful other developers learning language, clear example of creating custom font custom attributes using attributed string in swift. documentation confusing there not clear path on how so. plan create attributed string , add end of coffeeamount string.
var coffeeamount: string = calculatedcoffee + attributedtext
where calculatedcoffee int converted string , "attributedtext" lowercase "g" customized font trying create. maybe i'm going wrong way. appreciated!
this answer has been updated swift 3.0.
quick reference
the general form making , setting attributed string this. can find other common options below.
// create attributed string let mystring = "swift attributed string" let myattribute = [ nsforegroundcolorattributename: uicolor.blue ] let myattrstring = nsattributedstring(string: mystring, attributes: myattribute) // set attributed text on uilabel mylabel.attributedtext = myattrstring
let myattribute = [ nsforegroundcolorattributename: uicolor.blue ]
let myattribute = [ nsbackgroundcolorattributename: uicolor.yellow ]
let myattribute = [ nsfontattributename: uifont(name: "chalkduster", size: 18.0)! ]
let myattribute = [ nsunderlinestyleattributename: nsunderlinestyle.stylesingle.rawvalue ]
let myshadow = nsshadow() myshadow.shadowblurradius = 3 myshadow.shadowoffset = cgsize(width: 3, height: 3) myshadow.shadowcolor = uicolor.gray let myattribute = [ nsshadowattributename: myshadow ]
the rest of post gives more detail interested.
attributes
string attributes dictionary in form of [string: any]
, string
key name of attribute , any
value of type. value font, color, integer, or else. there many standard attributes in swift have been predefined. example:
- key name:
nsfontattributename
, value:uifont
- key name:
nsforegroundcolorattributename
, value:uicolor
- key name:
nslinkattributename
, value:nsurl
orstring
there many others. see this link more. can make own custom attributes.
- key name:
mycustomattributename
, value: type.
creating attributes in swift
you can declare attributes declaring other dictionary.
// single attributes declared 1 @ time let singleattribute1 = [ nsforegroundcolorattributename: uicolor.green ] let singleattribute2 = [ nsbackgroundcolorattributename: uicolor.yellow ] let singleattribute3 = [ nsunderlinestyleattributename: nsunderlinestyle.styledouble.rawvalue ] // multiple attributes declared @ once let multipleattributes: [string : any] = [ nsforegroundcolorattributename: uicolor.green, nsbackgroundcolorattributename: uicolor.yellow, nsunderlinestyleattributename: nsunderlinestyle.styledouble.rawvalue ] // custom attribute let customattribute = [ "mycustomattributename": "some value" ]
note rawvalue
needed underline style value.
because attributes dictionaries, can create them making empty dictionary , adding key-value pairs it. if value contain multiple types, have use any
type. here multipleattributes
example above, recreated in fashion:
var multipleattributes = [string : any]() multipleattributes[nsforegroundcolorattributename] = uicolor.green multipleattributes[nsbackgroundcolorattributename] = uicolor.yellow multipleattributes[nsunderlinestyleattributename] = nsunderlinestyle.styledouble.rawvalue
attributed strings
now understand attributes, can make attributed strings.
initialization
there few ways create attributed strings. if need read-only string can use nsattributedstring
. here ways initialize it:
// initialize string let attrstring1 = nsattributedstring(string: "hello.") // initialize string , inline attribute(s) let attrstring2 = nsattributedstring(string: "hello.", attributes: ["mycustomattribute": "a value"]) // initialize string , separately declared attribute(s) let myattributes1 = [ nsforegroundcolorattributename: uicolor.green ] let attrstring3 = nsattributedstring(string: "hello.", attributes: myattributes1)
if need change attributes or string content later, should use nsmutableattributedstring
. declarations similar:
// create blank attributed string let mutableattrstring1 = nsmutableattributedstring() // initialize string let mutableattrstring2 = nsmutableattributedstring(string: "hello.") // initialize string , inline attribute(s) let mutableattrstring3 = nsmutableattributedstring(string: "hello.", attributes: ["mycustomattribute": "a value"]) // initialize string , separately declared attribute(s) let myattributes2 = [ nsforegroundcolorattributename: uicolor.green ] let mutableattrstring4 = nsmutableattributedstring(string: "hello.", attributes: myattributes2)
changing attributed string
as example, let's create attributed string @ top of post.
first create nsmutableattributedstring
new font attribute.
let myattribute = [ nsfontattributename: uifont(name: "chalkduster", size: 18.0)! ] let mystring = nsmutableattributedstring(string: "swift", attributes: myattribute )
if working along, set attributed string uitextview
(or uilabel
) this:
textview.attributedtext = mystring
you don't use textview.text
.
here result:
then append attributed string doesn't have attributes set. (notice though used let
declare mystring
above, can still modify because nsmutableattributedstring
. seems rather unswiftlike me , wouldn't surprised if changes in future. leave me comment when happens.)
let attrstring = nsattributedstring(string: " attributed strings") mystring.append(attrstring)
next we'll select "strings" word, starts @ index 17
, has length of 7
. notice nsrange
, not swift range
. (see this answer more ranges.) addattribute
method lets put attribute key name in first spot, attribute value in second spot, , range in third spot.
var myrange = nsrange(location: 17, length: 7) // range starting @ location 17 lenth of 7: "strings" mystring.addattribute(nsforegroundcolorattributename, value: uicolor.red, range: myrange)
finally, let's add background color. variety, let's use addattributes
method (note s
). add multiple attributes @ once method, add 1 again.
myrange = nsrange(location: 3, length: 17) let anotherattribute = [ nsbackgroundcolorattributename: uicolor.yellow ] mystring.addattributes(anotherattribute, range: myrange)
notice attributes overlapping in places. adding attribute doesn't overwrite attribute there.
related
further reading
- how retrieve attributes tap location
- attributed string programming guide (very informitive unfortunately in objective-c)