Let’s discuss five techniques for dealing with right-to-left layout across Apple platforms, using 11 different APIs. Be sure to check out the handy dandy chart at the end, and Apple’s Building Apps for the World webpage. Let’s get started, in order of oldest API to newest.

Inference By Writing Direction using NSLocale

The first technique is inferring the device’s direction, using two class methods on NSLocale. characterDirection(forLanguage:) and lineDirection(forLanguage:) take an ISO language code, such as en-US or he-IL and return a direction. You can get a valid value to pass into these methods from NSLocale’s languageCode property.

These class methods are supported as far back as iOS 4.0 and are safe to use in app extensions. They also exist on other Apple platforms: macOS 10.6, tvOS 9.0, and watchOS 2.0. I wouldn’t base the majority of my app’s layout on it, but it’s certainly useful to have them in your toolkit.

It’s also notable that, unlike the other APIs mentioned here, these methods can return top-to-bottom and bottom-to-top, besides for the expected left-to-right and right-to-left values. English, for example, has a character direction of left-to-right and line direction of top-to-bottom.

In my experiments with Xcode Playgrounds, I did not find any macOS languages that assigned a line direction that wasn’t top-to-bottom.

Explicit Layout Direction with UIApplication & NSApplication

The second technique is to reference UIApplication’s userInterfaceLayoutDirection property. This is probably the earliest API explicitly for view layout. Available since iOS 5.0, this property determines the general direction of the app. NSApplication has this property, too, as of macOS 10.6.

On both platforms, userInterfaceLayoutDirection is either .rightToLeft or .leftToRight, based on the user’s systemwide preferences. The catch here is that since this property is accessible on a sharedApplication instance, it won’t work in app extensions.

Another Writing Direction Trick, with NSParagraphStyle

NSParagraphStyle gives us another way to check for the default text layout direction. defaultWritingDirectionForLanguage(_:) takes an ISO language code, and returns one of three NSWritingDirection values: .natural, .leftToRight, or .rightToLeft. This was added to iOS 6 with a slew of typesetting improvements, and was around on macOS since 10.2. You can override the writing direction of an NSMutableParagraphStyle instance by setting its baseWritingDirection yourself.

UIView & NSView Semantic Content Attributes watchOS

Next up is UIView’s userInterfaceLayoutDirection(for attribute:) method. Added in iOS 9, you can use this to check the layout direction on a specific view or control. You can set the semanticContentAttribute manually, to force specific views to defy the rest of your app’s layout. You can use values such as .forceLeftToRight and .forceRightToLeft. The documentation says you should use this API for media playback controls. Another use case might be providing a manual language override for your app. (Really, though, just localize properly.)

There is a similar property on NSView called userInterfaceLayoutDirection. You can set it to an NSUserInterfaceLayoutDirection value: .leftToRight or .rightToLeft. WKInterfaceControl has a setSemanticContentAttribute(_:) method for watchOS 2.1 to set (but not get) the semantic content attributes.

The Modern Approach: UITraitCollection

Finally, there’s UITraitCollection, which was added in iOS 8 to help deal with the wide variety of screen resolutions stemming from all of the iOS device screen resolutions and orientations. Trait collections added a property in iOS 10 called layoutDirection. Since every UIView conforms to UITraitEnvironment, you can access this property on any UIView on iOS 10 or higher.

So there you have it. Five techniques to get and set layout direction on iOS, macOS, tvOS, and watchOS. Oh, here’s the chart:

Class Method Version Added
NSLocale characterDirection(forLanguage:) iOS 4, macOS 10.6, tvOS 9, watchOS 2
NSLocale lineDirection(forLanguage:) iOS 4, macOS 10.6, tvOS 9.0, watchOS 2
UIApplication userInterfaceLayoutDirection iOS 5, tvOS 9
NSApplication userInterfaceLayoutDirection macOS 10.6
NSParagraphStyle defaultWritingDirectionForLanguage(_:) iOS 6, macOS 10.2, tvOS 9, watchOS 2
NSParagraphStyle baseWritingDirection iOS 6, macOS 10.2, tvOS 9, watchOS 2
UIView userInterfaceLayoutDirection(for attribute:) iOS 9, tvOS 9
UIView semanticContentAttribute iOS 9, tvOS 9
NSView userInterfaceLayoutDirection macOS 10.6
WKInterfaceControl setSemanticContentAttribute(_:) iOS 8.2, watchOS 2.1
UITraitCollection layoutDirection iOS 10, tvOS 10

In case you missed the link above, here’s a link to download the bonus playground.