Я пытаюсь реализовать функцию смены языка в своем приложении SwiftUI, при которой, когда пользователь выбирает новый язык, приложение должно перезапуститься и отображаться на выбранном языке. В настоящее время язык меняется, но пользовательский интерфейс не обновляется полностью, пока приложение не будет перезапущено вручную.
Текущая реализация
Просмотр выбора языка
Код: Выделить всё
struct LanguageSelectionView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.tabBarVisibility) var tabBarVisibility
@StateObject private var localizationManager = LocalizationManager.shared
@State private var selectedLanguage: Language
@State private var showConfirmation = false
@State private var languageToChange: Language?
@AppStorage("restartKey") var restartKey: Bool = false
var body: some View {
NavigationView {
// ... UI implementation ...
.alert(isPresented: $showConfirmation) {
Alert(
title: Text("Change Language"),
message: Text("The app needs to restart to change the language. Do you want to continue?"),
primaryButton: .default(Text("Yes")) {
if let language = languageToChange {
LocalizationManager.shared.setLanguage(language)
restartKey.toggle() // This should trigger app restart
}
},
secondaryButton: .cancel()
)
}
}
}
}
Менеджер локализации
Код: Выделить всё
class LocalizationManager: ObservableObject {
static let shared = LocalizationManager()
@Published var currentLanguage: Language {
didSet {
UserDefaults.standard.set(currentLanguage.rawValue, forKey: "selectedLanguage")
Bundle.setLanguageBundle(currentLanguage)
NotificationCenter.default.post(name: Notification.Name("LanguageChanged"), object: nil)
}
}
@AppStorage("restartKey") var restartKey: Bool = false
func setLanguage(_ language: Language) {
guard language != currentLanguage else { return }
UserDefaults.standard.set([language.rawValue], forKey: "AppleLanguages")
UserDefaults.standard.set(language.rawValue, forKey: "selectedLanguage")
UserDefaults.standard.synchronize()
currentLanguage = language
// Attempt to trigger restart
DispatchQueue.main.async {
self.restartKey.toggle()
}
}
}
Основное приложение
Код: Выделить всё
@main
struct FaceAIEditApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject private var authManager = AuthenticationManager.shared
@StateObject private var localizationManager = LocalizationManager.shared
@AppStorage("restartKey") var restartKey: Bool = false
init() {
// Set initial language bundle on app launch
// TabBar appearance configuration
let tabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithOpaqueBackground()
tabBarAppearance.shadowColor = .clear
tabBarAppearance.backgroundColor = .clear
UITabBar.appearance().standardAppearance = tabBarAppearance
if #available(iOS 15.0, *) {
UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
}
}
var body: some Scene {
WindowGroup {
ZStack {
if authManager.isLoading {
// Show loading screen while checking auth state
ProgressView()
.scaleEffect(1.5)
.progressViewStyle(CircularProgressViewStyle(tint: .blue))
} else {
MainTabView()
.id(restartKey) // This triggers view rebuild on language change
.environment(\.locale, .init(identifier: localizationManager.currentLanguage.rawValue))
}
}
.environmentObject(authManager)
.environmentObject(localizationManager) // Add localizationManager as environment object
.environment(\.language, localizationManager.currentLanguage.rawValue)
.onAppear {
authManager.checkAndSignInAnonymously()
}
}
}
}
При смене языка:
- Язык сохраняется правильно.
- Некоторые элементы пользовательского интерфейса не обновляются.
- При перезапуске приложения вручную он обновляется. >
Как я могу программно перезапустить все приложение, когда пользователь выбирает новый язык, чтобы:
- приложение полностью перезапускалось;
- все представления обновлялись до нового языка;
Приложение возвращается в исходное состояние (корневой вид). - Изменение происходит плавно и удобно.
Я пробовал: - Используя @AppStorage("restartKey") для запуска обновлений,
- публикации уведомлений об изменении языка,
- принудительного обновления представлений с помощью модификатора .id,
Различные манипуляции с окном пользовательского интерфейса
- iOS 15+
- Swift 5.5
- SwiftUI
Xcode 14< /li>
Подробнее здесь: https://stackoverflow.com/questions/791 ... -selection
Мобильная версия