From d48b0142279644a0ad9119594e29aafad17f8b81 Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:12:53 +0900 Subject: [PATCH 1/8] =?UTF-8?q?[BOOK-435]=20chore:=20remote=20config=20pac?= =?UTF-8?q?kage=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Projects/BKData/Project.swift | 3 ++- src/Projects/Booket/Project.swift | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Projects/BKData/Project.swift b/src/Projects/BKData/Project.swift index b298306b..a696cb9e 100644 --- a/src/Projects/BKData/Project.swift +++ b/src/Projects/BKData/Project.swift @@ -17,7 +17,8 @@ let project = Project.project( .domain(), .external(dependency: .KakaoSDKCommon), .external(dependency: .KakaoSDKAuth), - .external(dependency: .KakaoSDKUser) + .external(dependency: .KakaoSDKUser), + .external(dependency: .FirebaseRemoteConfig) ] ), Target.target( diff --git a/src/Projects/Booket/Project.swift b/src/Projects/Booket/Project.swift index 150b2976..de6e56b1 100644 --- a/src/Projects/Booket/Project.swift +++ b/src/Projects/Booket/Project.swift @@ -31,7 +31,8 @@ let debugAppTarget = Target.target( .external(dependency: .FirebaseCore), .external(dependency: .FirebaseCrashlytics), .external(dependency: .FirebaseAnalytics), - .external(dependency: .FirebaseMessaging) + .external(dependency: .FirebaseMessaging), + .external(dependency: .FirebaseRemoteConfig) ], settings: .settings( base: [ @@ -76,7 +77,8 @@ let releaseAppTarget = Target.target( .external(dependency: .FirebaseCore), .external(dependency: .FirebaseCrashlytics), .external(dependency: .FirebaseAnalytics), - .external(dependency: .FirebaseMessaging) + .external(dependency: .FirebaseMessaging), + .external(dependency: .FirebaseRemoteConfig) ], settings: .settings( base: [ From 3212a3ddad9e752ad5c31627358a9e7162cdb03a Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:13:36 +0900 Subject: [PATCH 2/8] =?UTF-8?q?[BOOK-435]=20feat:=20appversion=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20entity=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20repo=20in?= =?UTF-8?q?terface=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BKDomain/Sources/Entity/RemoteAppVersion.swift | 13 +++++++++++++ .../Repository/RemoteConfigRepository.swift | 8 ++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift create mode 100644 src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift diff --git a/src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift b/src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift new file mode 100644 index 00000000..9d34b1af --- /dev/null +++ b/src/Projects/BKDomain/Sources/Entity/RemoteAppVersion.swift @@ -0,0 +1,13 @@ +// Copyright © 2025 Booket. All rights reserved + +import Foundation + +public struct RemoteAppVersion { + public let latestVersion: String + public let minimumRequiredVersion: String + + public init(latestVersion: String, minimumRequiredVersion: String) { + self.latestVersion = latestVersion + self.minimumRequiredVersion = minimumRequiredVersion + } +} diff --git a/src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift b/src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift new file mode 100644 index 00000000..cec3c0b6 --- /dev/null +++ b/src/Projects/BKDomain/Sources/Interface/Repository/RemoteConfigRepository.swift @@ -0,0 +1,8 @@ +// Copyright © 2025 Booket. All rights reserved + +import Combine +import Foundation + +public protocol RemoteConfigRepository { + func fetchRemoteAppVersions() -> AnyPublisher +} From f3cad22c7134699398c5d103d014024c4fb0c13f Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:19:00 +0900 Subject: [PATCH 3/8] =?UTF-8?q?[BOOK-435]=20feat:=20remoteConfig=20Repo=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultRemoteConfigRepository.swift | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift diff --git a/src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift b/src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift new file mode 100644 index 00000000..ac0d50a4 --- /dev/null +++ b/src/Projects/BKData/Sources/Repository/DefaultRemoteConfigRepository.swift @@ -0,0 +1,59 @@ +// Copyright © 2025 Booket. All rights reserved + +import BKDomain +import Combine +import Foundation +import FirebaseRemoteConfig + +enum RemoteConfigKeys { + static let latestVersion = "appleLatestVersion" + static let minimumRequiredVersion = "appleMinimumVersion" +} + +public struct DefaultRemoteConfigRepository: RemoteConfigRepository { + + private let remoteConfig: RemoteConfig + + public init(remoteConfig: RemoteConfig) { + self.remoteConfig = remoteConfig + self.setDefaults() + } + + public func fetchRemoteAppVersions() -> AnyPublisher { + return Future { promise in + self.remoteConfig.fetchAndActivate { status, error in + if let error = error { + promise(.failure(error)) + return + } + + if status != .error { + let latest = self.remoteConfig.configValue( + forKey: RemoteConfigKeys.latestVersion + ).stringValue + + let minimum = self.remoteConfig.configValue( + forKey: RemoteConfigKeys.minimumRequiredVersion + ).stringValue + + let versions = RemoteAppVersion( + latestVersion: latest, + minimumRequiredVersion: minimum + ) + promise(.success(versions)) + } else { + promise(.failure(URLError(.cannotParseResponse))) + } + } + } + .eraseToAnyPublisher() + } + + private func setDefaults() { + let defaultValues: [String: NSObject] = [ + RemoteConfigKeys.latestVersion: "0.0.0" as NSObject, + RemoteConfigKeys.minimumRequiredVersion: "0.0.0" as NSObject + ] + self.remoteConfig.setDefaults(defaultValues) + } +} From 873ef7ed129f7349d266c5ecd15bea6fb45ee3e5 Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:24:49 +0900 Subject: [PATCH 4/8] =?UTF-8?q?[BOOK-435]=20feat:=20FetchRemoteAppVersion?= =?UTF-8?q?=20usecase=20=EC=84=A4=EA=B3=84,=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20DI=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BKDomain/Sources/DomainAssembly.swift | 5 +++++ .../Usecase/FetchRemoteAppVersionUseCase.swift | 9 +++++++++ .../DefaultFetchRemoteAppVersionUseCase.swift | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift create mode 100644 src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift diff --git a/src/Projects/BKDomain/Sources/DomainAssembly.swift b/src/Projects/BKDomain/Sources/DomainAssembly.swift index 3a15b441..431e5ac8 100644 --- a/src/Projects/BKDomain/Sources/DomainAssembly.swift +++ b/src/Projects/BKDomain/Sources/DomainAssembly.swift @@ -70,6 +70,11 @@ public struct DomainAssembly: Assembly { return DefaultAppVersionUseCase(repository: repository) } + container.register(type: FetchRemoteAppVersionUseCase.self) { _ in + @Autowired var repository: RemoteConfigRepository + return DefaultFetchRemoteAppVersionUseCase(repository: repository) + } + container.register( type: SearchBookUseCase.self ) { _ in diff --git a/src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift b/src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift new file mode 100644 index 00000000..1375ae71 --- /dev/null +++ b/src/Projects/BKDomain/Sources/Interface/Usecase/FetchRemoteAppVersionUseCase.swift @@ -0,0 +1,9 @@ +// Copyright © 2025 Booket. All rights reserved + +import Combine +import Foundation + +/// Remote Config에서 앱 버전 정보(최신, 최소)를 가져옵니다. +public protocol FetchRemoteAppVersionUseCase { + func execute() -> AnyPublisher +} diff --git a/src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift b/src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift new file mode 100644 index 00000000..f4aa9e30 --- /dev/null +++ b/src/Projects/BKDomain/Sources/UseCase/DefaultFetchRemoteAppVersionUseCase.swift @@ -0,0 +1,17 @@ +// Copyright © 2025 Booket. All rights reserved + +import Combine +import Foundation + +public struct DefaultFetchRemoteAppVersionUseCase: FetchRemoteAppVersionUseCase { + + private let repository: RemoteConfigRepository + + public init(repository: RemoteConfigRepository) { + self.repository = repository + } + + public func execute() -> AnyPublisher { + return repository.fetchRemoteAppVersions() + } +} From 672c8de6d69b70529b3ed957d9c2372cb3853eca Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:50:13 +0900 Subject: [PATCH 5/8] =?UTF-8?q?[BOOK-435]=20feat:=20assembly=EC=97=90=20DI?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Projects/BKData/Sources/DataAssembly.swift | 15 +++++++++++++++ .../BKDomain/Sources/DomainAssembly.swift | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Projects/BKData/Sources/DataAssembly.swift b/src/Projects/BKData/Sources/DataAssembly.swift index 28bb79ff..134ecdcc 100644 --- a/src/Projects/BKData/Sources/DataAssembly.swift +++ b/src/Projects/BKData/Sources/DataAssembly.swift @@ -3,6 +3,7 @@ import BKCore import BKDomain import Foundation +import FirebaseRemoteConfig public struct DataAssembly: Assembly { public init() {} @@ -129,6 +130,20 @@ public struct DataAssembly: Assembly { @Autowired var networkProvider: NetworkProvider return DefaultAppStoreRepository(networkProvider: networkProvider) } + + container.register( + type: RemoteConfigRepository.self, + scope: .singleton) { _ in + let remoteConfig = RemoteConfig.remoteConfig() + let settings = RemoteConfigSettings() +#if DEBUG + settings.minimumFetchInterval = 0 +#endif + settings.minimumFetchInterval = 10 + remoteConfig.configSettings = settings + return DefaultRemoteConfigRepository(remoteConfig: remoteConfig) + } + container.register( type: NotificationRepository.self diff --git a/src/Projects/BKDomain/Sources/DomainAssembly.swift b/src/Projects/BKDomain/Sources/DomainAssembly.swift index 431e5ac8..dbf3d40b 100644 --- a/src/Projects/BKDomain/Sources/DomainAssembly.swift +++ b/src/Projects/BKDomain/Sources/DomainAssembly.swift @@ -70,7 +70,9 @@ public struct DomainAssembly: Assembly { return DefaultAppVersionUseCase(repository: repository) } - container.register(type: FetchRemoteAppVersionUseCase.self) { _ in + container.register( + type: FetchRemoteAppVersionUseCase.self + ) { _ in @Autowired var repository: RemoteConfigRepository return DefaultFetchRemoteAppVersionUseCase(repository: repository) } From 77ba5ed62cbff6170009543121d0189738362919 Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:50:59 +0900 Subject: [PATCH 6/8] =?UTF-8?q?[BOOK-435]=20feat:=20AppCoordinator,=20Scen?= =?UTF-8?q?eDelegate=20usecase=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/AppCoordinator.swift | 61 ++++++++++++++----- .../Booket/Sources/SceneDelegate.swift | 2 + 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/Projects/BKPresentation/Sources/AppCoordinator.swift b/src/Projects/BKPresentation/Sources/AppCoordinator.swift index f2d8de5a..26812b27 100644 --- a/src/Projects/BKPresentation/Sources/AppCoordinator.swift +++ b/src/Projects/BKPresentation/Sources/AppCoordinator.swift @@ -19,6 +19,7 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, private let onboardingCheckUseCase: OnboardingCheckUseCase private let markOnboardingSeenUseCase: MarkOnboardingSeenUseCase private let appVersionUseCase: AppVersionUseCase + private let fetchRemoteAppVersionUseCase: FetchRemoteAppVersionUseCase private let syncFCMTokenUseCase: SyncFCMTokenUseCase private var cancellable: Set = [] @@ -28,6 +29,7 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, onboardingCheckUseCase: OnboardingCheckUseCase, markOnboardingSeenUseCase: MarkOnboardingSeenUseCase, appVersionUseCase: AppVersionUseCase, + fetchRemoteAppVersionUseCase: FetchRemoteAppVersionUseCase, syncFCMTokenUseCase: SyncFCMTokenUseCase ) { self.navigationController = navigationController @@ -35,6 +37,7 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, self.onboardingCheckUseCase = onboardingCheckUseCase self.markOnboardingSeenUseCase = markOnboardingSeenUseCase self.appVersionUseCase = appVersionUseCase + self.fetchRemoteAppVersionUseCase = fetchRemoteAppVersionUseCase self.syncFCMTokenUseCase = syncFCMTokenUseCase } @@ -67,25 +70,35 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, private func checkAppUpdate() { Publishers.Zip( appVersionUseCase.execute().setFailureType(to: Error.self), - appVersionUseCase.executeRecentVersion() + fetchRemoteAppVersionUseCase.execute() ) .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] completion in if case .failure = completion { self?.proceedWithAppFlow() } - }, receiveValue: { [weak self] currentVersionString, latestVersionString in + }, receiveValue: { [weak self] currentVersionString, remoteVersions in guard let self = self, let currentVersion = Version(currentVersionString), - let latestVersion = Version(latestVersionString) + let minimumVersion = Version(remoteVersions.minimumRequiredVersion), + let latestVersion = Version(remoteVersions.latestVersion) else { self?.proceedWithAppFlow() return } - if currentVersion.isMajorOrMinorUpdateRequired(from: latestVersion) { - self.presentUpdateSheet() - } else { + Log.debug("currentVersionString: \(currentVersionString)", logger: AppLogger.ui) + Log.debug("minimumRequiredVersion: \(remoteVersions.minimumRequiredVersion)", logger: AppLogger.ui) + Log.debug("latestVersion: \(remoteVersions.latestVersion)", logger: AppLogger.ui) + + if currentVersion < minimumVersion { + self.presentUpdateSheet() // 강업 + } + else if currentVersion < latestVersion { + self.presentUpdateSheet(isForced: false) // 권장 + self.proceedWithAppFlow() + } + else { self.proceedWithAppFlow() } }) @@ -203,16 +216,34 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, .store(in: &cancellable) } - private func presentUpdateSheet() { - let dialog = BKDialog( - title: "최신 버전이 출시되었습니다", - subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", - config: .init( - leftButtonTitle: "업데이트 하기", - leftButtonAction: AppStoreLinker.openAppStore + private func presentUpdateSheet(isForced: Bool = true) { + var dialog: BKDialog? + + if isForced { + dialog = BKDialog( + title: "최신 버전이 출시되었습니다", + subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", + config: .init( + leftButtonTitle: "업데이트 하기", + leftButtonAction: AppStoreLinker.openAppStore + ) ) - ) - + } else { + dialog = BKDialog( + title: "최신 버전이 출시되었습니다", + subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", + config: .init( + leftButtonTitle: "업데이트 하기", + leftButtonAction: AppStoreLinker.openAppStore, + rightButtonTitle: "나중에 하기", + rightButtonAction: { [weak self] in + self?.navigationController.dismiss(animated: true) + } + ) + ) + } + + guard let dialog else { return } let dialogViewController = BKDialogViewController(dialog: dialog) dialogViewController.isModalInPresentation = true DispatchQueue.main.async { diff --git a/src/Projects/Booket/Sources/SceneDelegate.swift b/src/Projects/Booket/Sources/SceneDelegate.swift index 9e18738d..1c21ad20 100644 --- a/src/Projects/Booket/Sources/SceneDelegate.swift +++ b/src/Projects/Booket/Sources/SceneDelegate.swift @@ -59,6 +59,7 @@ private extension SceneDelegate { @Autowired var onboardingCheckUseCase: OnboardingCheckUseCase @Autowired var markOnboardingSeenUseCase: MarkOnboardingSeenUseCase @Autowired var appVersionUseCase: AppVersionUseCase + @Autowired var fetchRemoteAppVersionUseCase: FetchRemoteAppVersionUseCase @Autowired var syncFCMTokenUseCase: SyncFCMTokenUseCase self.coordinator = AppCoordinator( @@ -67,6 +68,7 @@ private extension SceneDelegate { onboardingCheckUseCase: onboardingCheckUseCase, markOnboardingSeenUseCase: markOnboardingSeenUseCase, appVersionUseCase: appVersionUseCase, + fetchRemoteAppVersionUseCase: fetchRemoteAppVersionUseCase, syncFCMTokenUseCase: syncFCMTokenUseCase ) coordinator?.start() From 07105bf4ba8ab5510675b68f033a14c9ce26025d Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Tue, 11 Nov 2025 23:16:28 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[BOOK-435]=20fix:=20release=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=EB=8A=94=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EA=B0=92=2012h=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Projects/BKData/Sources/DataAssembly.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Projects/BKData/Sources/DataAssembly.swift b/src/Projects/BKData/Sources/DataAssembly.swift index 134ecdcc..ac54e2c5 100644 --- a/src/Projects/BKData/Sources/DataAssembly.swift +++ b/src/Projects/BKData/Sources/DataAssembly.swift @@ -137,9 +137,8 @@ public struct DataAssembly: Assembly { let remoteConfig = RemoteConfig.remoteConfig() let settings = RemoteConfigSettings() #if DEBUG - settings.minimumFetchInterval = 0 + settings.minimumFetchInterval = 0 #endif - settings.minimumFetchInterval = 10 remoteConfig.configSettings = settings return DefaultRemoteConfigRepository(remoteConfig: remoteConfig) } From f004f05e18019464e88c9dd6def751b7b52a2243 Mon Sep 17 00:00:00 2001 From: doyeonk429 <80318425+doyeonk429@users.noreply.github.com> Date: Thu, 13 Nov 2025 22:21:51 +0900 Subject: [PATCH 8/8] =?UTF-8?q?[BOOK-435]=20fix:=20=ED=86=A0=EB=81=BC=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BKPresentation/Sources/AppCoordinator.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Projects/BKPresentation/Sources/AppCoordinator.swift b/src/Projects/BKPresentation/Sources/AppCoordinator.swift index 26812b27..7221f7ad 100644 --- a/src/Projects/BKPresentation/Sources/AppCoordinator.swift +++ b/src/Projects/BKPresentation/Sources/AppCoordinator.swift @@ -96,7 +96,6 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, } else if currentVersion < latestVersion { self.presentUpdateSheet(isForced: false) // 권장 - self.proceedWithAppFlow() } else { self.proceedWithAppFlow() @@ -229,6 +228,7 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, ) ) } else { + // TODO(dyk) : 디자인 파트와 논의 후 subtitle 수정하기 dialog = BKDialog( title: "최신 버전이 출시되었습니다", subtitle: "최적의 사용 환경을 위해 업데이트해주세요.", @@ -237,7 +237,10 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, leftButtonAction: AppStoreLinker.openAppStore, rightButtonTitle: "나중에 하기", rightButtonAction: { [weak self] in - self?.navigationController.dismiss(animated: true) + guard let self else { return } + self.navigationController.dismiss(animated: true) { + self.proceedWithAppFlow() + } } ) ) @@ -246,9 +249,7 @@ public final class AppCoordinator: Coordinator, AuthenticationRequiredNotifying, guard let dialog else { return } let dialogViewController = BKDialogViewController(dialog: dialog) dialogViewController.isModalInPresentation = true - DispatchQueue.main.async { - self.navigationController.present(dialogViewController, animated: true) - } + navigationController.present(dialogViewController, animated: true) } private func requestNotificationPermissionIfNeeded() {