2

I'm having problems with UILabels that use NSAttributedStrings with NSParagraphStyle when I use UISemanticContentAttributeForceRightToLeft.

I have a demo app with just 2 labels on the UI.

They have leading and trailing constraints.

The two labels

I'm making the app Right to Left in the AppDelegate with

UIView.appearance().semanticContentAttribute = .forceRightToLeft

And I'm just configuring the labels with the following code

let labelAText = "Foo"

let mutAttrString = NSMutableAttributedString(string: labelAText)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.baseWritingDirection = .natural

mutAttrString.setAttributes([NSAttributedStringKey.paragraphStyle: paragraphStyle.copy()], range: NSMakeRange(0, labelAText.count))

labelA.attributedText = mutAttrString
labelB.text = "Bar"

Which results in this:

[wrong label[2]

The labelB (Bar) is working as expected, but the labelA (Foo) isn't. And if I just remove the NSParagraphStyle it starts working. Mind that I'm not even changing anything on it, but just by using it it's messing up with the alignment.

Any thoughts on what might be causing this?

miguel.gazela
  • 143
  • 2
  • 14

1 Answers1

2

NSMutableParagraphStyle has a property baseWritingDirection (enum NSWritingDirection). Set it to rightToLeft

Try this

paragraphStyle.baseWritingDirection = NSWritingDirection.rightToLeft


Edit:(May this help you)

If the value of property (baseWritingDirection) is NSWritingDirectionNaturalDirection, the receiver resolves the writing direction to either NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft, depending on the direction for the user’s language preference setting.

class func defaultWritingDirection(forLanguage languageName: String?) -> NSWritingDirection

languageName: The language specified in ISO language region format. Can be nil to return a default writing direction derived from the user’s defaults database.


Solution using languageName = "ar"

@IBOutlet weak var labelA: UILabel!

let labelAText = "Foo"
let mutAttrString = NSMutableAttributedString(string: "Foo")
let paragraphStyle = NSMutableParagraphStyle()
//paragraphStyle.alignment = .natural
paragraphStyle.baseWritingDirection = NSParagraphStyle.defaultWritingDirection(forLanguage: "ar")
mutAttrString.setAttributes([NSAttributedStringKey.paragraphStyle: paragraphStyle], range: NSMakeRange(0, labelAText.count))

labelA.attributedText = mutAttrString

Here is list of languages: Codes for the Representation of Names of Languages

Note: Use ISO 639-1 code for language. Direction of label text depends upon natural direction of language.

Here is result:

enter image description here


This Apple document will help you - Supporting Right-to-Left Languages

Krunal
  • 77,632
  • 48
  • 245
  • 261
  • Hey, thanks for the suggestion, but I don't want to force the rightToLeft direction, I wanted it to determine it by itself, like the other label does it. I'm using `natural`. – miguel.gazela Jan 18 '18 at 16:53
  • @miguel.gazela I agree with your concern. You are absolutely right. Code should be dynamic (without force update). May `defaultWritingDirection` help you. – Krunal Jan 18 '18 at 17:12
  • Yeah, it works like that, and it's definitely one way of solving it. But the original problem remains. Why isn't the alignment and baseWritingDirection set as natural enough to make it flip like an ordinary text label? That's what I would like to know. But thanks! – miguel.gazela Jan 18 '18 at 17:36
  • @miguel.gazela There is an answer to your question: `If you the value of this property is NSWritingDirectionNaturalDirection, the receiver resolves the writing direction to either NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft, depending on the direction for the user’s language preference setting.` What is natural language for your label? It should be English (en) right? So it follows direction of language english. – Krunal Jan 18 '18 at 17:38
  • no, I've changed the device language to Arabic, I've used Arabic strings, and it still displays the `labelA` on the left of the screen. – miguel.gazela Jan 18 '18 at 17:42