0

I am internally switching the App Language (LTR-RTL) and then re-initializing the storyboard.

here is the piece of code:

let semanticContentAttribute: UISemanticContentAttribute = language == .Arabic ? .ForceRightToLeft : .ForceLeftToRight

UIView.appearance().semanticContentAttribute = semanticContentAttribute
UINavigationBar.appearance().semanticContentAttribute = semanticContentAttribute

The issue is, all the presented view controllers freezes for 3-6 seconds while dismissing it.

What is causing this?

Burhanuddin Sunelwala
  • 5,318
  • 3
  • 25
  • 51
  • Did you find any solution to this – Mr. SS Dec 08 '17 at 07:59
  • The issue was that are too many views in the app. there are many internal views from the iOS framework itself. For example, if you initialize a UISearchBar, the UISearchBar itself have a UITextField, a UILabel, a Cancel Button, a Clear Button, a background view and etc. Therefore, it was taking time to switch each and every view from LTR to RTL. Solution: I created an extension for UIView, and added an IBDesignable attribute - a Bool. So, when ever I create a UIView in a .xib file, I just check this property so it will only switch this particular view and not each and every view inside it. – Burhanuddin Sunelwala Dec 08 '17 at 11:19
  • Thanks for the answer – Mr. SS Dec 08 '17 at 11:50
  • Please help a little more. Did you used any other method instead of UIView.appearance().semanticContentAttribute. Or did you overrided any UIView method. – Mr. SS Dec 08 '17 at 12:21

2 Answers2

0

Setting semanticContentAttribute on the appearance() proxy is not supported. You're going to run into many other issues and bugs since the app still believes it's running in a language that isn't the one you're overriding.

Adding a language switcher to your app is only going to make it more confusing; users expect their apps to follow the language that their device is set to.

wakachamo
  • 1,723
  • 1
  • 12
  • 18
0

I found the solution for it after searching long time, if someone seeks.

The reason that the UI freezes / hangs is because the UINavigationController is missing a check for the root view controller when the gesture is executed on the root view. There a few ways to fix that, the following is what I did.

You should subclass UINavigationController, this is the right way to go and add implement as followed:

class RTLNavController: UINavigationController, UINavigationControllerDelegate, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //  Adding swipe to pop viewController
        self.interactivePopGestureRecognizer?.isEnabled = true
        self.interactivePopGestureRecognizer?.delegate = self

        //  UINavigationControllerDelegate
        self.delegate = self
    }
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        navigationController.view.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
        navigationController.navigationBar.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
    }

    //  Checking if the viewController is last, if not disable the gesture
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if self.viewControllers.count > 1 {
            return true
        }
        
        return false
    }
}

extension UIView {
    static func isRightToLeft() -> Bool {
        return UIView.appearance().semanticContentAttribute == .forceRightToLeft
    }
}

Resources:

Original question:

The answer is used for the solution:

Other solution which may work better (But it's in Objective-C):

ytpm
  • 4,962
  • 6
  • 56
  • 113