Does anyone have any idea why my right-to-left (RTL) layout isn't taking effect immediately?

37 Views Asked by At

I'm working on integrating RTL (right-to-left) and LTR (left-to-right) layouts into my application, and everything seems to be functioning properly. However, I've encountered an issue: when I initially select 'en', my app adopts the LTR layout as expected. But when I switch the language to 'Arabic', the semanticContentAttribute appearance changes perfectly. However, at the same time, UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft returns false, which is correct. When I switch the language, the widgets don't shift their layout, such as the placeholder of a UITextField.

What could be causing this behavior?


//
//  SceneDelegate.swift
//  ____
//
//  Created by XYZ on 10/02/2024.
//

import UIKit
import Floaty

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    var window: UIWindow?
    var scene: UIWindowScene?
    
    var mainNavigationController: UINavigationController!
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let scene = (scene as? UIWindowScene) else { return }
        self.scene = scene
        SharedManager.manager.updateLanguage()
        NotificationCenter.default.addObserver(self, selector: #selector(languageReset(notification:)), name: .languageReset, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(changeRootVc(notification:)), name: .changeVc, object: nil)
    }
    
    @objc func changeRootVc(notification: NSNotification){
        if let scene {
            setupLaunchScreen(scene: scene, vc: MainTabbarViewController.instantiate(for: .Main))
        }
    }
    
    @objc func languageReset(notification: NSNotification) {
        
        if let scene {
            
            if notification.userInfo?["isLanguageAlreadySetUp"] as? Bool ?? false {
                setupLaunchScreen(scene: scene, vc: MainTabbarViewController.instantiate(for: .Main))
            } else {
                setupLaunchScreen(scene: scene, vc: LanguageSelectionViewController.instantiate(for: .Main))
            }
            
        }
    }
    
    func setupLaunchScreen(scene: UIWindowScene, vc: UIViewController){
        
        SharedManager.manager.updateLanguage()
        
        if SharedManager.manager.isArabicLanguage {
            Floaty.global.rtlMode = true
            UIView.appearance().semanticContentAttribute = .forceRightToLeft
        } else {
            Floaty.global.rtlMode = false
            UIView.appearance().semanticContentAttribute = .forceLeftToRight
        }
        
        self.window = UIWindow(windowScene: scene)
        mainNavigationController = UINavigationController(rootViewController: vc)
        mainNavigationController.setNavigationBarHidden(true, animated: false)
        UIView.transition(with: self.window!, duration: 0.5, options: .transitionCrossDissolve, animations: {
                self.window?.rootViewController = self.mainNavigationController
            }, completion: nil)
        self.window?.makeKeyAndVisible()
    
    }
    
}

The Language Handler


import Foundation

enum Language: String, CaseIterable {
    
    case english = "en"
    case arabic = "ar"
    
    static func enumFor(_ rawValue: RawValue) -> Language? {
        return Language(rawValue: rawValue)
    }

}

class SharedManager : NSObject {
    
    static let manager: SharedManager = SharedManager()
    
    var langDictionary: Dictionary<String, String>!
    private override init() {}
    
    var isArabicLanguage: Bool {
        return SharedManager.manager.language == .arabic
    }
    
    var isLangAlreadySet: Bool {
        return UserDefaults.standard.string(forKey: "language") != nil
    }
    
    func updateLanguage() {
        
        guard let currentLanguage = UserDefaults.standard.string(forKey: "language"),
              let language = Language.enumFor(currentLanguage) else {
            return
        }
        
        self.language = language
        self.checkLanguageSupport()
    }
    
    func checkLanguageSupport() {
        
        guard let path = Bundle.main.path(forResource: SharedManager.manager.language?.rawValue, ofType: "json"),
              let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
            print("Language file not found")
            return
        }
        
        do {
            langDictionary = try JSONSerialization.jsonObject(with: data, options: []) as? Dictionary<String, String>
        } catch {
            print("Error parsing language file")
        }
    }
    
    var language: Language? {
        didSet {
            guard let language = language else { return }
            SharedManager.manager.checkLanguageSupport()
            UserDefaults.standard.set([language.rawValue], forKey: "AppleLanguages")
            UserDefaults.standard.set(language.rawValue, forKey: "language")
        }
    }
}
0

There are 0 best solutions below