6

The question up front:

Can we directly access the font-weight and font-style information for an attributed string? Or can we create a new string for which we are able to set this information?

The explanation:

In iOS 6, you can toggle a selection as bold or italic. But the way this works is vexing: it does not change the NSFontAttributeName that Apple has exposed to us (changing the font name from, for instance, "HelveticaNeue" to "HelveticaNeue-Bold"). Instead, it preserves the font-family as "Helvetica Neue" and changes the "font-weight" to bold in the style string. If you were to ask an instance of attributed text for its description, you would see something like this for its font information:

NSFont = "<UICFFont: 0x1fbc53a0> font-family: \"Helvetica Neue\"; font-weight: bold; font-style: normal; font-size: 16px";

This creates a problem. We cannot change the font while preserving bold and italic style information. If you jump through the hoops of scanning the old attributed string for style info, creating a new string with a new font, and then changing the font attribute name (using, for instance, "Courier-Bold" for everywhere you want it to be bold), you create a new problem: if you try to toggle the font back to normal (not bold) you will instead have a font name like "Courier-Bold" AND a font-weight of "bold", because the style information was not yet set to bold. And toggling will not, of course, change the font name. So you've essentially created a font that can no longer be changed when the user toggles the selected text. The user will press the "bold" button in the contextual menu, but it will do nothing, because the boldness has now been hardcoded into the font name, you might say.

If you go the other route and try to override "toggleBoldface" and "toggleItalic" in your UITextView, it does not seem possible to actually prevent the style information in the style string from being changed. You cannot, it seems, change the font name alone during the toggle event.

So, again, the question: can we just access the font-weight and font-style information directly somehow? Or can we create a new string for which we are able to set this information? This would solve the problem of trying to switch from one font to another and preserving style info.

And a double clarification:

We are talking about iOS. When you set an attributed string's font attribute (NSFontAttributeName) for some range of characters, internally iOS creates an NSFont with a style string. The style string will read "font-weight: normal; font-style: normal" if you have set a font attribute yourself. But this style string is where the bold and italic information set in a UITextView (by toggling) is stored.

Steve Cotner
  • 505
  • 4
  • 14
  • 1
    You'll need to edit something in your question at least one more time: NSFont is for MacOS, while ***UIFont*** is for iOS; which architecture are you using and/or which font class are you using? – Michael Dautermann Nov 03 '12 at 20:27
  • I'm afraid that's not correct. You create an NSFontAttributeName as an attribute for your attributed string (by designating a UIFont), and internally iOS turns this into an NSFont. Thus, the code I included that says "NSFont" is what you will read if you ask a piece of attributed text for its description using NSLog. – Steve Cotner Nov 03 '12 at 20:34
  • More specifically, that NSFont information is part of what you will read if you ask an NSAttributedString for its description. – Steve Cotner Nov 03 '12 at 20:45

1 Answers1

1

Looks like you might be able to create a new CTFontRef using a CTFontAttributesRef where you have set value for attribute keys kCTFontWeightTrait and/or kCTFontSymbolicTrait. Does that help?

cf. CTFontDescriptorReference and CTFontReference

EDIT

Guess this won't work--I looked into it more myself... leaving this here in case someone else has the same idea.

nielsbot
  • 15,922
  • 4
  • 48
  • 73
  • Once that is created, how could it be applied to an NSAttributedString? When I'm creating a dictionary of attributes, for instance, can it be used instead of a UIFont when setting NSFontAttributeName? – Steve Cotner Nov 03 '12 at 21:08
  • Oh, I believe this answers my question: converting a CTFont to UIFont. http://stackoverflow.com/questions/6714858/iphone-convert-ctfont-to-uifont I will report back if there's a problem, or I'll accept the answer if it works. But I think you've gotten me on track. Thanks. – Steve Cotner Nov 03 '12 at 21:16
  • Ultimately I don't think this will work out. As I understand it (and after some attempts), you can't use CoreText fonts in a UITextView. Am I wrong about that? – Steve Cotner Nov 04 '12 at 01:12
  • Sorry. 'Tis no good. The issue is the same as with this Apple dev question on UICFFont and CTFont: https://devforums.apple.com/message/751433 – Steve Cotner Nov 04 '12 at 02:29
  • Thanks anyway for your help. The best hope seems to be avoiding using the SDK's toggling of bold face and italic and instead creating a similar action on your own (through your own interface), where the font name is set to a bold or italic name, and the style strings are not affected. – Steve Cotner Nov 05 '12 at 19:14