Alineación de texto AutoLayout + RTL + UILabel

Finalmente me estoy dando la vuelta para luchar con Auto Layout y no puedo entender cómo hacer que el soporte de derecha a izquierda (RTL) funcione de la manera que esperaría / querría …

He diseñado la vista en Interface Builder como se muestra:

IB

Con la aplicación resultante funcionando como se esperaba al usar el inglés:

Inglés

Sin embargo, al cambiar a un lenguaje RTL (en árabe en este caso), la vista entera se voltea (lo cual es genial) pero el texto de UILabel todavía se alinea a la izquierda. Esperaría que esté alineado correctamente para mantenerlo en contra del UIImageView .

Arábica

Claramente me falta algo y / o esto no está cubierto por el diseño automático.

¿Se supone que debo configurar textAlignment manualmente cuando uso un lenguaje RTL?

Desea NSTextAlignmentNatural . Eso infiere la alineación de texto del lenguaje de la aplicación cargada ( no del script).

Para iOS 9 y posteriores (usando Xcode 7), puede configurar esto en el guión gráfico (elija la opción — Alineación). Si necesita segmentar lanzamientos anteriores, deberá crear una salida a la etiqueta y establecer la alineación en awakeFromNib .

 - (void)awakeFromNib { [[self label] setTextAlignment:NSTextAlignmentNatural]; } 

Para mí, esas soluciones no ayudaron, y terminé haciendo algo bastante feo, pero es el único que hizo el truco para mí. Lo agregué como una categoría NSString :

NSString + Extras.h:

 #import  @interface NSString (Extras) - (NSTextAlignment)naturalTextAligment; @end 

NSString + Extras.m:

 #import "NSString+Extras.h" @implementation NSString (Extras) - (NSTextAlignment)naturalTextAligment { NSArray *tagschemes = [NSArray arrayWithObjects:NSLinguisticTagSchemeLanguage, nil]; NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:tagschemes options:0]; [tagger setString:self]; NSString *language = [tagger tagAtIndex:0 scheme:NSLinguisticTagSchemeLanguage tokenRange:NULL sentenceRange:NULL]; if ([language rangeOfString:@"he"].location != NSNotFound || [language rangeOfString:@"ar"].location != NSNotFound) { return NSTextAlignmentRight; } else { return NSTextAlignmentLeft; } } @end 

Para detectar el lenguaje, utilicé esta respuesta SO .

Creo que no desea usar alineación de texto en este caso, para una etiqueta.

Puedes dejar que el ancho sea determinado por intrinsicContentSize y eliminar cualquier restricción de ancho en la etiqueta. Conseguirá el efecto deseado del texto de la etiqueta alineado con la vista.

Para eje x, solo necesita esta restricción entre etiqueta e imagen: [imageview] – [label]

Esta es solo una restricción de espacio horizontal. Sin liderazgo ni seguimiento para supervisar.

Seguimiento de la respuesta de Ken

NSTextAlignmentNatural es posible configurar textAlignment a NSTextAlignmentNatural en UILabel , se generará una excepción:

 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'textAlignment does not accept NSTextAlignmentNatural' 

Funciona al usar texto atribuido y esto se puede configurar en el Interface Builder como se muestra:

alineación natural del texto atribuido

Sin embargo, parece que el texto atribuido no se recoge cuando se localiza el guión gráfico.

Para evitar esto, he dejado el UILabel configurado como simple en Interface Builder y NSAttributedString creado un NSAttributedString con el texto de la etiqueta, establezco la alineación en la cadena atribuida y la asigno a la propiedad attributedText la etiqueta:

 -(void)viewDidLoad { [super viewDidLoad]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.alignment = NSTextAlignmentNatural; NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:self.lbl.text]; [string addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, string.length)]; self.lbl.attributedText = string; } 

Esto funciona bien en este caso simple, pero puedo ver que se cae cuando necesitas un estilo de cuerda atribuido más complejo. Pero, obviamente, en ese caso, probablemente solo NSLocalizedString usando NSLocalizedString o equivalentes al crear NSAttributedString .

@Aviel responde como una rápida extensión UILabel

 //MARK: UILabel extension extension UILabel { func decideTextDirection () { let tagScheme = [NSLinguisticTagSchemeLanguage] let tagger = NSLinguisticTagger(tagSchemes: tagScheme, options: 0) tagger.string = self.text let lang = tagger.tagAtIndex(0, scheme: NSLinguisticTagSchemeLanguage, tokenRange: nil, sentenceRange: nil) if lang?.rangeOfString("he") != nil || lang?.rangeOfString("ar") != nil { self.textAlignment = NSTextAlignment.Right } else { self.textAlignment = NSTextAlignment.Left } } } 

Cómo usarlo ?

 label.text = "كتابة باللغة العربية" // Assign text label.decideTextDirection() // Decide direction 

puede usar MyLayout para facilitar el soporte de RTL y LRT.

Esta función me ayudó

 -(void)fnForWritingDirection:(UILabel*)label textFor:(NSString *)stringForText{ NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString: [stringForText stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; [paragraphStyle setBaseWritingDirection:NSWritingDirectionRightToLeft]; [attrStr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [attrStr length])]; label.attributedText=attrStr; }