If i get an attributed string from a text field using
let text = input.attributedText!
print(text)
in Swift, then the output is as follows (when the input contains "hello" in regular then "world" in bold)
hello {
NSColor = "UIDeviceWhiteColorSpace 0 1";
NSFont = "<UICTFont: 0x134544930> font-family: \".SFUIText-Regular\"; font-weight: normal; font-style: normal; font-size: 17.00pt";
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 2, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection 0, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";
NSShadow = "NSShadow {0, -1} color = {(null)}";
}
world{
NSColor = "UIDeviceWhiteColorSpace 0 1";
NSFont = "<UICTFont: 0x1345b12a0> font-family: \".SFUIText-Bold\"; font-weight: bold; font-style: normal; font-size: 17.00pt";
NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 2, Tabs (\n 28L,\n 56L,\n 84L,\n 112L,\n 140L,\n 168L,\n 196L,\n 224L,\n 252L,\n 280L,\n 308L,\n 336L\n), DefaultTabInterval 0, Blocks (\n), Lists (\n), BaseWritingDirection 0, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";
NSShadow = "NSShadow {0, -1} color = {(null)}";
}
I can see that the two blocks of differently formatted writing are represented in two blocks when printed to the console. Now what I want to do is loop through all the blocks and for each one, get the text and the font. So in this case, the first time it loops, it would find "Hello" and " font-family: \".SFUIText-Regular\"; font-weight: normal; font-style: normal; font-size: 17.00pt" and the second time it'd find "world" and it's font
I can loop through fonts using the code
text.enumerateAttribute(NSFontAttributeName, inRange: NSMakeRange(0, text.length), options: NSAttributedStringEnumerationOptions()) { (font: AnyObject?, range: NSRange, usmp: UnsafeMutablePointer<ObjCBool>) -> Void in
print(font)
}
Is there a way to do the same for the actual text?
Yes - just enumerate all of the attributes instead of just one.
Assuming you have an attributed string like this:
// Create the string
let text = NSMutableAttributedString(string: "hello world")
let font = UIFont(name: ".SFUIText-Regular", size: 17)!
let boldFont = UIFont(name: ".SFUIText-Bold", size: 17)!
text.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(), range: NSMakeRange(0, text.string.characters.count))
text.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, 6))
text.addAttribute(NSFontAttributeName, value: boldFont, range: NSMakeRange(6, 5))
You can create output similar to the one in your example like this:
// Enumerate the attributes
text.enumerateAttributesInRange(NSMakeRange(0, text.string.characters.count), options: []) { (attribute, range, stop) -> Void in
let substring = (text.string as NSString).substringWithRange(range)
debugPrint(substring, attribute)
}
The output looks like this:
"hello " ["NSFont": <UICTFont: 0x7fba19724be0> font-family: ".SFUIText-Regular"; font-weight: normal; font-style: normal; font-size: 17.00pt, "NSColor": UIDeviceWhiteColorSpace 0 1]
"world" ["NSFont": <UICTFont: 0x7fba1960d8d0> font-family: ".SFUIText-Bold"; font-weight: bold; font-style: normal; font-size: 17.00pt, "NSColor": UIDeviceWhiteColorSpace 0 1]