diff --git a/TOASTER-iOS.xcodeproj/project.pbxproj b/TOASTER-iOS.xcodeproj/project.pbxproj index eb4e5272..5083e52a 100644 --- a/TOASTER-iOS.xcodeproj/project.pbxproj +++ b/TOASTER-iOS.xcodeproj/project.pbxproj @@ -1911,7 +1911,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1530; - LastUpgradeCheck = 1620; + LastUpgradeCheck = 2630; TargetAttributes = { 3FF2BEFE2BA17492001D7DC1 = { CreatedOnToolsVersion = 15.3; @@ -2343,7 +2343,6 @@ CODE_SIGN_ENTITLEMENTS = ToasterShareExtension/ToasterShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = JF6B89ULG6; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ToasterShareExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ToasterShareExtension; @@ -2370,7 +2369,6 @@ CODE_SIGN_ENTITLEMENTS = ToasterShareExtension/ToasterShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = JF6B89ULG6; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ToasterShareExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ToasterShareExtension; @@ -2427,6 +2425,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = JF6B89ULG6; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -2450,8 +2449,11 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_STRICT_CONCURRENCY = complete; }; name = Debug; }; @@ -2491,6 +2493,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = JF6B89ULG6; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -2507,7 +2510,10 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_DEFAULT_ACTOR_ISOLATION = nonisolated; + SWIFT_STRICT_CONCURRENCY = complete; VALIDATE_PRODUCT = YES; }; name = Release; @@ -2521,7 +2527,6 @@ CODE_SIGN_ENTITLEMENTS = "TOASTER-iOS/TOASTER-iOS.entitlements"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = JF6B89ULG6; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "TOASTER-iOS/Global/Supporting Files/Info.plist"; @@ -2535,7 +2540,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; PRODUCT_BUNDLE_IDENTIFIER = "TeamLinkMIND.TOASTER-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -2555,7 +2560,6 @@ CODE_SIGN_ENTITLEMENTS = "TOASTER-iOS/TOASTER-iOS.entitlements"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = JF6B89ULG6; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = "TOASTER-iOS/Global/Supporting Files/Info.plist"; @@ -2569,7 +2573,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; PRODUCT_BUNDLE_IDENTIFIER = "TeamLinkMIND.TOASTER-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; diff --git a/TOASTER-iOS.xcodeproj/xcshareddata/xcschemes/TOASTER-iOS.xcscheme b/TOASTER-iOS.xcodeproj/xcshareddata/xcschemes/TOASTER-iOS.xcscheme index 90fca5cc..00172b4b 100644 --- a/TOASTER-iOS.xcodeproj/xcshareddata/xcschemes/TOASTER-iOS.xcscheme +++ b/TOASTER-iOS.xcodeproj/xcshareddata/xcschemes/TOASTER-iOS.xcscheme @@ -1,6 +1,6 @@ Void) { + func checkAppleLogin() async -> Bool { let appleIDProvider = ASAuthorizationAppleIDProvider() - appleIDProvider.getCredentialState(forUserID: UserDefaults.standard.string(forKey: Config.appleUserID) ?? "") { (credentialState, error) in - switch credentialState { - case .authorized: - print("해당 ID는 연동되어있습니다.") - completion(true) - case .revoked: - print("해당 ID는 연동되어있지않습니다.") - completion(false) - case .notFound: - print("해당 ID를 찾을 수 없습니다.") - completion(false) - default: - break + return await withCheckedContinuation { continuation in + appleIDProvider.getCredentialState(forUserID: UserDefaults.standard.string(forKey: Config.appleUserID) ?? "") { credentialState, _ in + switch credentialState { + case .authorized: + print("해당 ID는 연동되어있습니다.") + continuation.resume(returning: true) + case .revoked: + print("해당 ID는 연동되어있지 않습니다.") + continuation.resume(returning: false) + case .notFound: + print("해당 ID를 찾을 수 없습니다.") + continuation.resume(returning: false) + default: + continuation.resume(returning: false) + } } } } } // MARK: - MessagingDelegate + extension AppDelegate: MessagingDelegate { // FCM 토큰을 받았을 때 실행 - func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { + nonisolated func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { if let fcmToken { let _ = KeyChainService.saveFCMToken(fcmToken: fcmToken, key: Config.fcmTokenKey) } @@ -140,16 +146,20 @@ extension AppDelegate: MessagingDelegate { } extension AppDelegate: UNUserNotificationCenterDelegate { - - func userNotificationCenter(_ center: UNUserNotificationCenter, - didReceive response: UNNotificationResponse, - withCompletionHandler completionHandler: @escaping () -> Void) { - - if let navigationViewController = UIApplication.shared.keyWindow?.rootViewController as? ToasterNavigationController { - navigationViewController.popToRootViewController(animated: false) - if let tabBarController = navigationViewController.topViewController as? TabBarController { - tabBarController.selectedIndex = 0 + nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void) { + Task { @MainActor in + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let navigationViewController = windowScene.windows + .first(where: { $0.isKeyWindow })? + .rootViewController as? ToasterNavigationController { + navigationViewController.popToRootViewController(animated: false) + if let tabBarController = navigationViewController.topViewController as? TabBarController { + tabBarController.selectedIndex = 0 + } } } + completionHandler() } } diff --git a/TOASTER-iOS/Application/Coordinator/Coordinator.swift b/TOASTER-iOS/Application/Coordinator/Coordinator.swift index 68266a34..c0237bb8 100644 --- a/TOASTER-iOS/Application/Coordinator/Coordinator.swift +++ b/TOASTER-iOS/Application/Coordinator/Coordinator.swift @@ -7,6 +7,7 @@ import Foundation +@MainActor protocol Coordinator: AnyObject { var childCoordinators: [Coordinator] { get set } func start() diff --git a/TOASTER-iOS/Application/Coordinator/CoordinatorFinishOutput.swift b/TOASTER-iOS/Application/Coordinator/CoordinatorFinishOutput.swift index cc996c85..73d80e94 100644 --- a/TOASTER-iOS/Application/Coordinator/CoordinatorFinishOutput.swift +++ b/TOASTER-iOS/Application/Coordinator/CoordinatorFinishOutput.swift @@ -7,6 +7,7 @@ import Foundation +@MainActor protocol CoordinatorFinishOutput { var onFinish: (() -> Void)? { get set } } diff --git a/TOASTER-iOS/Application/Coordinator/Coordinators/TabBarCoordinator.swift b/TOASTER-iOS/Application/Coordinator/Coordinators/TabBarCoordinator.swift index 83a53853..9893c913 100644 --- a/TOASTER-iOS/Application/Coordinator/Coordinators/TabBarCoordinator.swift +++ b/TOASTER-iOS/Application/Coordinator/Coordinators/TabBarCoordinator.swift @@ -149,7 +149,9 @@ private extension TabBarCoordinator { accessKey: Config.accessTokenKey, refreshKey: Config.refreshTokenKey ) - self?.onFinish?() + Task { @MainActor in + self?.onFinish?() + } } } } diff --git a/TOASTER-iOS/Application/Coordinator/Factory/CoordinatorFactory.swift b/TOASTER-iOS/Application/Coordinator/Factory/CoordinatorFactory.swift index 548da376..07e909ac 100644 --- a/TOASTER-iOS/Application/Coordinator/Factory/CoordinatorFactory.swift +++ b/TOASTER-iOS/Application/Coordinator/Factory/CoordinatorFactory.swift @@ -7,6 +7,7 @@ import UIKit +@MainActor protocol CoordinatorFactoryProtocol { func makeTabBarCoordinator( router: RouterProtocol, diff --git a/TOASTER-iOS/Application/Coordinator/Factory/ViewControllerFactory.swift b/TOASTER-iOS/Application/Coordinator/Factory/ViewControllerFactory.swift index 4142f4d2..ea825848 100644 --- a/TOASTER-iOS/Application/Coordinator/Factory/ViewControllerFactory.swift +++ b/TOASTER-iOS/Application/Coordinator/Factory/ViewControllerFactory.swift @@ -7,6 +7,7 @@ import Foundation +@MainActor protocol ViewControllerFactoryProtocol { func makeLoginVC() -> LoginViewController func makeTabBarVC() -> TabBarController diff --git a/TOASTER-iOS/Application/Coordinator/Router.swift b/TOASTER-iOS/Application/Coordinator/Router.swift index 20c28cbb..4f27fbd8 100644 --- a/TOASTER-iOS/Application/Coordinator/Router.swift +++ b/TOASTER-iOS/Application/Coordinator/Router.swift @@ -7,6 +7,7 @@ import UIKit +@MainActor protocol RouterProtocol: AnyObject { func setRoot(_ viewController: UIViewController, animated: Bool) func setRoot(_ viewController: UIViewController, animated: Bool, hideBottomBarWhenPushed: Bool) diff --git a/TOASTER-iOS/Global/Resources/Config.swift b/TOASTER-iOS/Global/Resources/Config.swift index ef57c0de..3bd1a37e 100644 --- a/TOASTER-iOS/Global/Resources/Config.swift +++ b/TOASTER-iOS/Global/Resources/Config.swift @@ -23,7 +23,7 @@ enum Config { } } - private static let infoDictionary: [String: Any] = { + nonisolated(unsafe) private static let infoDictionary: [String: Any] = { guard let dict = Bundle.main.infoDictionary else { fatalError("plist cannot found !!!") } diff --git a/TOASTER-iOS/Network/Base/APIInterceptor.swift b/TOASTER-iOS/Network/Base/APIInterceptor.swift index 4b94e63e..03e1f107 100644 --- a/TOASTER-iOS/Network/Base/APIInterceptor.swift +++ b/TOASTER-iOS/Network/Base/APIInterceptor.swift @@ -16,7 +16,7 @@ final class APIInterceptor: RequestInterceptor { /// 재발급을 받고 다시 기존 API 를 호출해야하기 때문에 Requset 의 Header 를 변경해야 한다. /// 해당 프로퍼티가 true 일 경우 기존의 Requset 의 Header 를 변경 /// 재발급을 받은 적이 없는 false 의 경우 TargetType 을 통해 Header 를 설정한 Requset 를 기본으로 사용 - private var isTokenRefreshed = false + nonisolated(unsafe) private var isTokenRefreshed = false static let shared = APIInterceptor() diff --git a/TOASTER-iOS/Network/Base/NetworkService.swift b/TOASTER-iOS/Network/Base/NetworkService.swift index 47c7fee8..aabe5c4f 100644 --- a/TOASTER-iOS/Network/Base/NetworkService.swift +++ b/TOASTER-iOS/Network/Base/NetworkService.swift @@ -9,7 +9,7 @@ import Foundation final class NetworkService { - static let shared = NetworkService() + nonisolated(unsafe) static let shared = NetworkService() private init() {} diff --git a/TOASTER-iOS/Present/AddLink/AddLinkViewController.swift b/TOASTER-iOS/Present/AddLink/AddLinkViewController.swift index c4fed385..dfdc0f1c 100644 --- a/TOASTER-iOS/Present/AddLink/AddLinkViewController.swift +++ b/TOASTER-iOS/Present/AddLink/AddLinkViewController.swift @@ -402,8 +402,11 @@ private extension AddLinkViewController { loadingTitle: "저장 중...", loadingAnimationSize: 16, task: { _ in - DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) { [weak self] in - self?.requestSaveLink.send() + Task { + try? await Task.sleep(for: .seconds(0.5)) + await MainActor.run { [weak self] in + self?.requestSaveLink.send() + } } } ) diff --git a/TOASTER-iOS/Present/AddLink/View/SelectClipHeaderView.swift b/TOASTER-iOS/Present/AddLink/View/SelectClipHeaderView.swift index 15f79a01..9e20777f 100644 --- a/TOASTER-iOS/Present/AddLink/View/SelectClipHeaderView.swift +++ b/TOASTER-iOS/Present/AddLink/View/SelectClipHeaderView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol SelectClipHeaderViewlDelegate: AnyObject { func addClipCellTapped() } diff --git a/TOASTER-iOS/Present/Clip/View/Component/AddClipBottomSheetView.swift b/TOASTER-iOS/Present/Clip/View/Component/AddClipBottomSheetView.swift index 8b040fbe..716b5d80 100644 --- a/TOASTER-iOS/Present/Clip/View/Component/AddClipBottomSheetView.swift +++ b/TOASTER-iOS/Present/Clip/View/Component/AddClipBottomSheetView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol AddClipBottomSheetViewDelegate: AnyObject { func addHeightBottom() func minusHeightBottom() diff --git a/TOASTER-iOS/Present/Clip/View/Component/ClipCollectionHeaderView.swift b/TOASTER-iOS/Present/Clip/View/Component/ClipCollectionHeaderView.swift index 55df5a2a..794bd549 100644 --- a/TOASTER-iOS/Present/Clip/View/Component/ClipCollectionHeaderView.swift +++ b/TOASTER-iOS/Present/Clip/View/Component/ClipCollectionHeaderView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol ClipCollectionHeaderViewDelegate: AnyObject { func addClipButtonTapped() } diff --git a/TOASTER-iOS/Present/DetailClip/View/Cell/DetailClipListCollectionViewCell.swift b/TOASTER-iOS/Present/DetailClip/View/Cell/DetailClipListCollectionViewCell.swift index 70a33f69..3d93540f 100644 --- a/TOASTER-iOS/Present/DetailClip/View/Cell/DetailClipListCollectionViewCell.swift +++ b/TOASTER-iOS/Present/DetailClip/View/Cell/DetailClipListCollectionViewCell.swift @@ -11,6 +11,7 @@ import Kingfisher import SnapKit import Then +@MainActor protocol DetailClipListCollectionViewCellDelegate: AnyObject { func modifiedButtonTapped(toastId: Int) } diff --git a/TOASTER-iOS/Present/DetailClip/View/Component/ChangeClipBottomSheetView.swift b/TOASTER-iOS/Present/DetailClip/View/Component/ChangeClipBottomSheetView.swift index 30c8f1ee..15585ef2 100644 --- a/TOASTER-iOS/Present/DetailClip/View/Component/ChangeClipBottomSheetView.swift +++ b/TOASTER-iOS/Present/DetailClip/View/Component/ChangeClipBottomSheetView.swift @@ -109,9 +109,12 @@ private extension ChangeClipBottomSheetView { loadingTitle: "이동 중...", loadingAnimationSize: 16, task: { completion in - DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) { - self.delegate?.completButtonTap() - completion() + Task { + try? await Task.sleep(for: .seconds(0.5)) + await MainActor.run { + self.delegate?.completButtonTap() + completion() + } } } ) @@ -174,6 +177,7 @@ extension ChangeClipBottomSheetView: UICollectionViewDelegateFlowLayout { } } +@MainActor protocol ChangeClipBottomSheetViewDelegate: AnyObject { func didSelectClip(selectClipId: Int) func completButtonTap() diff --git a/TOASTER-iOS/Present/Home/View/Cell/UserClipCollectionViewCell.swift b/TOASTER-iOS/Present/Home/View/Cell/UserClipCollectionViewCell.swift index e036fa15..8a6dd3ba 100644 --- a/TOASTER-iOS/Present/Home/View/Cell/UserClipCollectionViewCell.swift +++ b/TOASTER-iOS/Present/Home/View/Cell/UserClipCollectionViewCell.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol UserClipCollectionViewCellDelegate: AnyObject { func addClipCellTapped() } diff --git a/TOASTER-iOS/Present/Home/View/Component/CompositioinalFactory.swift b/TOASTER-iOS/Present/Home/View/Component/CompositioinalFactory.swift index f3219115..e1539626 100644 --- a/TOASTER-iOS/Present/Home/View/Component/CompositioinalFactory.swift +++ b/TOASTER-iOS/Present/Home/View/Component/CompositioinalFactory.swift @@ -9,6 +9,7 @@ import UIKit // MARK: - Compositional Layout +@MainActor enum CompositionalFactory { static func create() -> UICollectionViewCompositionalLayout { return UICollectionViewCompositionalLayout { (sectionNumber, _ environment) -> NSCollectionLayoutSection? in diff --git a/TOASTER-iOS/Present/LinkWeb/ViewController/LinkWebViewController.swift b/TOASTER-iOS/Present/LinkWeb/ViewController/LinkWebViewController.swift index 19db4c19..0ef01db2 100644 --- a/TOASTER-iOS/Present/LinkWeb/ViewController/LinkWebViewController.swift +++ b/TOASTER-iOS/Present/LinkWeb/ViewController/LinkWebViewController.swift @@ -141,8 +141,10 @@ private extension LinkWebViewController { progressObservation = $0.observe( \.estimatedProgress, options: [.new]) { [weak self] object, _ in - let progress = Float(object.estimatedProgress) - self?.progressView.progress = progress + MainActor.assumeIsolated { + let progress = Float(object.estimatedProgress) + self?.progressView.progress = progress + } } } } diff --git a/TOASTER-iOS/Present/Login/Adapter/KakaoAuthenticateAdapter.swift b/TOASTER-iOS/Present/Login/Adapter/KakaoAuthenticateAdapter.swift index 522ad2b4..bf5c0a27 100644 --- a/TOASTER-iOS/Present/Login/Adapter/KakaoAuthenticateAdapter.swift +++ b/TOASTER-iOS/Present/Login/Adapter/KakaoAuthenticateAdapter.swift @@ -52,7 +52,6 @@ final class KakaoAuthenticateAdapter: NSObject, AuthenticationAdapterProtocol { } /// 카카오톡 간편로그인을 통해 토큰을 받아오는 메서드 - @MainActor func getLoginToken() async throws -> SocialLoginTokenModel { return try await withCheckedThrowingContinuation { continuation in UserApi.shared.loginWithKakaoTalk {(oauthToken, error) in @@ -72,7 +71,6 @@ final class KakaoAuthenticateAdapter: NSObject, AuthenticationAdapterProtocol { } /// 카카오톡 간편로그인을 할 수 없는 경우 웹에서 이메일로 로그인 해서 토큰을 받아오는 메서드 - @MainActor func getTokenKakaoAccount() async throws -> SocialLoginTokenModel { return try await withCheckedThrowingContinuation { continuation in UserApi.shared.loginWithKakaoAccount {(oauthToken, error) in diff --git a/TOASTER-iOS/Present/Remind/View/Component/RemindAlarmOffBottomSheetView.swift b/TOASTER-iOS/Present/Remind/View/Component/RemindAlarmOffBottomSheetView.swift index 6d792753..84a7c096 100644 --- a/TOASTER-iOS/Present/Remind/View/Component/RemindAlarmOffBottomSheetView.swift +++ b/TOASTER-iOS/Present/Remind/View/Component/RemindAlarmOffBottomSheetView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol RemindAlarmOffBottomSheetViewDelegate: AnyObject { func alarmButtonTapped() } diff --git a/TOASTER-iOS/Present/Remind/View/Component/RemindTimerEditBottomSheetView.swift b/TOASTER-iOS/Present/Remind/View/Component/RemindTimerEditBottomSheetView.swift index b6dcd1f0..c82d4112 100644 --- a/TOASTER-iOS/Present/Remind/View/Component/RemindTimerEditBottomSheetView.swift +++ b/TOASTER-iOS/Present/Remind/View/Component/RemindTimerEditBottomSheetView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol RemindEditViewDelegate: AnyObject { func editTimer(forID: Int?) func deleteTimer(forID: Int?) diff --git a/TOASTER-iOS/Present/Remind/ViewModel/RemindViewModel.swift b/TOASTER-iOS/Present/Remind/ViewModel/RemindViewModel.swift index 674855bd..ac5e97b6 100644 --- a/TOASTER-iOS/Present/Remind/ViewModel/RemindViewModel.swift +++ b/TOASTER-iOS/Present/Remind/ViewModel/RemindViewModel.swift @@ -25,9 +25,7 @@ final class RemindViewModel { /// RemindViewType을 저장하기 위한 프로퍼티 private var remindViewType: RemindViewType = .deviceOnAppOnNoneData { didSet { - DispatchQueue.main.async { - self.dataChangeAction?(self.remindViewType) - } + self.dataChangeAction?(self.remindViewType) } } diff --git a/TOASTER-iOS/Present/RemindAdd/TimerAdd/View/TimerRepeatBottomSheetView.swift b/TOASTER-iOS/Present/RemindAdd/TimerAdd/View/TimerRepeatBottomSheetView.swift index ac6fefd0..47e9ca62 100644 --- a/TOASTER-iOS/Present/RemindAdd/TimerAdd/View/TimerRepeatBottomSheetView.swift +++ b/TOASTER-iOS/Present/RemindAdd/TimerAdd/View/TimerRepeatBottomSheetView.swift @@ -10,6 +10,7 @@ import UIKit import SnapKit import Then +@MainActor protocol TimerRepeatBottomSheetDelegate: AnyObject { func nextButtonTapped(selectedList: Set) } diff --git a/TOASTER-iOS/Present/UpdateAlert/UpdateAlertManager.swift b/TOASTER-iOS/Present/UpdateAlert/UpdateAlertManager.swift index 77e53d4d..4476d44a 100644 --- a/TOASTER-iOS/Present/UpdateAlert/UpdateAlertManager.swift +++ b/TOASTER-iOS/Present/UpdateAlert/UpdateAlertManager.swift @@ -7,10 +7,11 @@ import UIKit -final class UpdateAlertManager { +struct UpdateAlertManager { private let appId = "6476194200" /// Alert 표출 함수 + @MainActor func showUpdateAlert(type: UpdateAlertType, on viewController: UIViewController) { let alertViewController = UIAlertController(title: type.title,