Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] #225 - 강제업데이트 추가 및 로그인 오류 개선 #228

Merged
merged 2 commits into from
Jan 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions iOS-NOTTODO/iOS-NOTTODO.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
09F6719029CB6AB400708725 /* OnboardingFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F6718F29CB6AB400708725 /* OnboardingFooterView.swift */; };
09F6719529CBFCD200708725 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F6719429CBFCD200708725 /* GradientView.swift */; };
09F6719729CC81B500708725 /* DetailAchievementCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F6719629CC81B500708725 /* DetailAchievementCollectionViewCell.swift */; };
155E45532B5BB8AC008628E7 /* API_KEY.plist in Resources */ = {isa = PBXBuildFile; fileRef = 155E45522B5BB8AC008628E7 /* API_KEY.plist */; };
155E45662B5FF089008628E7 /* FirebaseRemoteConfig in Frameworks */ = {isa = PBXBuildFile; productRef = 155E45652B5FF089008628E7 /* FirebaseRemoteConfig */; };
155E45692B5FF2EE008628E7 /* FirebaseUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 155E45682B5FF2EE008628E7 /* FirebaseUtil.swift */; };
155E456D2B62B1A1008628E7 /* UpdateCheckViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 155E456C2B62B1A1008628E7 /* UpdateCheckViewController.swift */; };
3B027A78299C31B500BEB65C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B027A77299C31B500BEB65C /* AppDelegate.swift */; };
3B027A7A299C31B500BEB65C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B027A79299C31B500BEB65C /* SceneDelegate.swift */; };
3B027A7C299C31B500BEB65C /* AuthViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B027A7B299C31B500BEB65C /* AuthViewController.swift */; };
Expand Down Expand Up @@ -151,7 +155,6 @@
6CA208362A1957CA001C4247 /* AuthAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CA208352A1957CA001C4247 /* AuthAPI.swift */; };
6CA2083A2A195906001C4247 /* AuthResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CA208392A195906001C4247 /* AuthResponseDTO.swift */; };
6CA2B7BB2A222D2300A9E549 /* ValueOnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CA2B7BA2A222D2300A9E549 /* ValueOnboardingViewController.swift */; };
6CBE702D2A5AA29E00A7EC30 /* API_KEY.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6CBE702C2A5AA29E00A7EC30 /* API_KEY.plist */; };
6CC54C1A2A28C3AE00AAD76D /* value.json in Resources */ = {isa = PBXBuildFile; fileRef = 6CC54C192A28C3AE00AAD76D /* value.json */; };
6CD4F8BA29AA493600CCC740 /* RecommendActionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4F8B929AA493600CCC740 /* RecommendActionHeaderView.swift */; };
6CD4F8BC29AA494300CCC740 /* RecommendActionFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD4F8BB29AA494300CCC740 /* RecommendActionFooterView.swift */; };
Expand Down Expand Up @@ -224,6 +227,9 @@
09F6718F29CB6AB400708725 /* OnboardingFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingFooterView.swift; sourceTree = "<group>"; };
09F6719429CBFCD200708725 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
09F6719629CC81B500708725 /* DetailAchievementCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailAchievementCollectionViewCell.swift; sourceTree = "<group>"; };
155E45522B5BB8AC008628E7 /* API_KEY.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = API_KEY.plist; sourceTree = "<group>"; };
155E45682B5FF2EE008628E7 /* FirebaseUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseUtil.swift; sourceTree = "<group>"; };
155E456C2B62B1A1008628E7 /* UpdateCheckViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateCheckViewController.swift; sourceTree = "<group>"; };
3B027A74299C31B500BEB65C /* iOS-NOTTODO.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS-NOTTODO.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3B027A77299C31B500BEB65C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
3B027A79299C31B500BEB65C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -301,7 +307,6 @@
6CA208352A1957CA001C4247 /* AuthAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthAPI.swift; sourceTree = "<group>"; };
6CA208392A195906001C4247 /* AuthResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthResponseDTO.swift; sourceTree = "<group>"; };
6CA2B7BA2A222D2300A9E549 /* ValueOnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValueOnboardingViewController.swift; sourceTree = "<group>"; };
6CBE702C2A5AA29E00A7EC30 /* API_KEY.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = API_KEY.plist; sourceTree = "<group>"; };
6CC54C192A28C3AE00AAD76D /* value.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = value.json; sourceTree = "<group>"; };
6CD4F8B929AA493600CCC740 /* RecommendActionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendActionHeaderView.swift; sourceTree = "<group>"; };
6CD4F8BB29AA494300CCC740 /* RecommendActionFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendActionFooterView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -335,6 +340,7 @@
6C44127129A35A1000313C3F /* KakaoSDK in Frameworks */,
3B146DA4299D0A8600B17B62 /* Then in Frameworks */,
3B146DA7299D0AA300B17B62 /* Moya in Frameworks */,
155E45662B5FF089008628E7 /* FirebaseRemoteConfig in Frameworks */,
3B2B59442AEB814B00B4619A /* FirebaseMessaging in Frameworks */,
6C44127729A35A1000313C3F /* KakaoSDKNavi in Frameworks */,
6C44128129A35A1000313C3F /* KakaoSDKUser in Frameworks */,
Expand Down Expand Up @@ -594,13 +600,45 @@
path = ViewControllers;
sourceTree = "<group>";
};
155E45642B5FF089008628E7 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
155E45672B5FF2DE008628E7 /* External */ = {
isa = PBXGroup;
children = (
155E45682B5FF2EE008628E7 /* FirebaseUtil.swift */,
);
path = External;
sourceTree = "<group>";
};
155E456A2B62B17D008628E7 /* UpdateCheck */ = {
isa = PBXGroup;
children = (
155E456B2B62B18F008628E7 /* ViewControllers */,
);
path = UpdateCheck;
sourceTree = "<group>";
};
155E456B2B62B18F008628E7 /* ViewControllers */ = {
isa = PBXGroup;
children = (
155E456C2B62B1A1008628E7 /* UpdateCheckViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
};
3B027A6B299C31B500BEB65C = {
isa = PBXGroup;
children = (
3B710A5B2A62D4AB00E95620 /* Settings.bundle */,
3BDE6157299EDD02001CCEA9 /* .swiftlint.yml */,
3B027A76299C31B500BEB65C /* iOS-NOTTODO */,
3B027A75299C31B500BEB65C /* Products */,
155E45642B5FF089008628E7 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -681,6 +719,7 @@
3B027A90299C33CA00BEB65C /* Network */ = {
isa = PBXGroup;
children = (
155E45672B5FF2DE008628E7 /* External */,
093DB0312A1468F100ECA5F6 /* Service */,
093DB02F2A1468CE00ECA5F6 /* DataModel */,
093DB02B2A14687300ECA5F6 /* API */,
Expand All @@ -692,6 +731,7 @@
3B027A97299C343D00BEB65C /* Presentation */ = {
isa = PBXGroup;
children = (
155E456A2B62B17D008628E7 /* UpdateCheck */,
3B03D0D32B0F157700302872 /* NotificatoinDialog */,
09F6717E29CAD68100708725 /* Onboarding */,
3B027A9B299C348800BEB65C /* Achievement */,
Expand Down Expand Up @@ -769,7 +809,7 @@
3B027AA6299C359900BEB65C /* Resource */ = {
isa = PBXGroup;
children = (
6CBE702C2A5AA29E00A7EC30 /* API_KEY.plist */,
155E45522B5BB8AC008628E7 /* API_KEY.plist */,
3B3EF2F72AF35C90001F79BC /* GoogleService-Info.plist */,
3B027A85299C31B600BEB65C /* Info.plist */,
3B027AAA299C35D000BEB65C /* Assets */,
Expand Down Expand Up @@ -1170,6 +1210,7 @@
0943A9F42A531D0000614761 /* Amplitude */,
09C8602C2AB14B4800C4F4B1 /* FSCalendar */,
3B2B59432AEB814B00B4619A /* FirebaseMessaging */,
155E45652B5FF089008628E7 /* FirebaseRemoteConfig */,
);
productName = "iOS-NOTTODO";
productReference = 3B027A74299C31B500BEB65C /* iOS-NOTTODO.app */;
Expand Down Expand Up @@ -1231,11 +1272,11 @@
3B710A5C2A62D4AB00E95620 /* Settings.bundle in Resources */,
3B027A84299C31B600BEB65C /* LaunchScreen.storyboard in Resources */,
6CC54C1A2A28C3AE00AAD76D /* value.json in Resources */,
155E45532B5BB8AC008628E7 /* API_KEY.plist in Resources */,
3B3EF2F82AF35C90001F79BC /* GoogleService-Info.plist in Resources */,
6C049A312A595C670085E40B /* logo.mp4 in Resources */,
3B027A81299C31B600BEB65C /* Assets.xcassets in Resources */,
3B146D9A299D079D00B17B62 /* Pretendard-Light.otf in Resources */,
6CBE702D2A5AA29E00A7EC30 /* API_KEY.plist in Resources */,
3B146D98299D077800B17B62 /* Pretendard-Medium.otf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1330,6 +1371,7 @@
6CA208302A1925EE001C4247 /* RecommendActionResponseDTO.swift in Sources */,
09F6718629CB26E400708725 /* OnboardingHeaderView.swift in Sources */,
3B11740D2A4B574B0033DDF3 /* CALayer+.swift in Sources */,
155E456D2B62B1A1008628E7 /* UpdateCheckViewController.swift in Sources */,
3B14A13D29A6FBD300F92897 /* UIView+.swift in Sources */,
09F6719529CBFCD200708725 /* GradientView.swift in Sources */,
3B4E12F82A27C12F001D1EC1 /* WithdrawModalView.swift in Sources */,
Expand Down Expand Up @@ -1393,6 +1435,7 @@
3B0CBA222A45FC170004F2DB /* UpdateMissionResponseDTO.swift in Sources */,
3B892ABE2A2FBDDE00A316BC /* AddMissionAPI.swift in Sources */,
092C09B72A48596500E9B06B /* DeleteModalView.swift in Sources */,
155E45692B5FF2EE008628E7 /* FirebaseUtil.swift in Sources */,
6CF4706329A690CD008D145C /* NetworkResult.swift in Sources */,
3B9532F42A284CC1006510F8 /* ModalProtocol.swift in Sources */,
3B5F8F8329BF90290063A7F8 /* SituationCollectionViewCell.swift in Sources */,
Expand Down Expand Up @@ -1716,6 +1759,11 @@
package = 09C8602B2AB14B4700C4F4B1 /* XCRemoteSwiftPackageReference "FSCalendar" */;
productName = FSCalendar;
};
155E45652B5FF089008628E7 /* FirebaseRemoteConfig */ = {
isa = XCSwiftPackageProductDependency;
package = 3B2B59422AEB814B00B4619A /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseRemoteConfig;
};
3B146DA0299D0A7A00B17B62 /* SnapKit */ = {
isa = XCSwiftPackageProductDependency;
package = 3B146D9F299D0A7A00B17B62 /* XCRemoteSwiftPackageReference "SnapKit" */;
Expand Down
112 changes: 2 additions & 110 deletions iOS-NOTTODO/iOS-NOTTODO/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Amplitude

import Firebase
import FirebaseMessaging
import FirebaseRemoteConfig

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
Expand All @@ -27,9 +28,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
Amplitude.instance().initializeApiKey(Bundle.main.amplitudeAPIKey)
KakaoSDK.initSDK(appKey: Bundle.main.kakaoAPIKey)
FirebaseApp.configure()

checkForUpdate()


// 메시지 대리자 설정
Messaging.messaging().delegate = self

Expand All @@ -42,20 +41,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return true
}

func skipAuthView() {
// 홈 화면으로 바로 이동
DispatchQueue.main.async {
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first {
let tabBarController = TabBarController()
let navigationController = UINavigationController(rootViewController: tabBarController)
navigationController.isNavigationBarHidden = true
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
}
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken

Expand Down Expand Up @@ -99,96 +84,3 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
completionHandler()
}
}

extension AppDelegate {
func checkForUpdate() {
// 앱스토어 버전
guard let appstoreVersion = getAppstoreVersion() else { return }

// 현재 설치된 앱의 버전
guard let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else { return }

if compareVersion(userVersion: appVersion, appstoreVersion: appstoreVersion) {
DispatchQueue.main.async {
self.showUpdateAlert()
}
} else {
if KeychainUtil.getAccessToken() != "" {
self.skipAuthView()
print("토큰 유효")
}
}
}

/// 버전 비교하는 메서드
func compareVersion(userVersion: String, appstoreVersion: String) -> Bool {
let userMajor = userVersion.split(separator: ".").map {Int($0)!}[0]
let appstoreMajor = appstoreVersion.split(separator: ".").map {Int($0)!}[0]

if userMajor < appstoreMajor {
return true
}

let userMinor = userVersion.split(separator: ".").map {Int($0)!}[1]
let appstoreMinor = appstoreVersion.split(separator: ".").map {Int($0)!}[1]

if userMinor < appstoreMinor {
return true
}

let userPatch = userVersion.split(separator: ".").map {Int($0)!}[2]
let appstorePatch = appstoreVersion.split(separator: ".").map {Int($0)!}[2]

if userPatch < appstorePatch {
return true
}

return false
}

/// 앱스토어에 배포된 버전 가져오는 메서드
func getAppstoreVersion() -> String? {
let appleID = Bundle.main.appleId
guard let url = URL(string: "https://itunes.apple.com/lookup?id=\(appleID)"),
let data = try? Data(contentsOf: url),
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
let results = json["results"] as? [[String: Any]],
let appStoreVersion = results[0]["version"] as? String else {
return nil
}
return appStoreVersion
}

/// 선택 업데이트 경고창
func showUpdateAlert() {
let alertController = UIAlertController(
title: I18N.update,
message: I18N.updateAlert,
preferredStyle: .alert
)

let updateAction = UIAlertAction(title: I18N.update, style: .default) { _ in
// App Store로 이동
if let appStoreURL = URL(string: "https://itunes.apple.com/app/\(Bundle.main.appleId)") {
UIApplication.shared.open(appStoreURL, options: [:], completionHandler: {_ in
if KeychainUtil.getAccessToken() != "" {
self.skipAuthView()
print("토큰 유효")
}
})
}
}

let cancelAction = UIAlertAction(title: I18N.later, style: .default)

alertController.addAction(updateAction)
alertController.addAction(cancelAction)

if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
if let keyWindow = windowScene.windows.first,
let rootViewController = keyWindow.rootViewController {
rootViewController.present(alertController, animated: true, completion: nil)
}
}
}
}
3 changes: 1 addition & 2 deletions iOS-NOTTODO/iOS-NOTTODO/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
let window = UIWindow(windowScene: windowScene)
window.overrideUserInterfaceStyle = UIUserInterfaceStyle.light

let rootViewController = ValueOnboardingViewController()
let rootViewController = UpdateCheckViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
navigationController.isNavigationBarHidden = true
window.rootViewController = navigationController
Expand Down Expand Up @@ -52,7 +52,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}

extension SceneDelegate {

func changeRootViewControllerTo(_ viewController: UIViewController) {
guard let window = window else { return }

Expand Down
3 changes: 3 additions & 0 deletions iOS-NOTTODO/iOS-NOTTODO/Global/Literals/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ struct I18N {
최신 업데이트가 있습니다.
업데이트하시겠습니까?
"""
static func forceUpdateAlert(newVersion: String) -> String {
return "낫투두의 새로운 버전이 있습니다. \(newVersion)버전 으로 업데이트 해주세요."
}
static let later = "나중에"
static let notiDialogTitle = """
알림을 허용하면
Expand Down
47 changes: 47 additions & 0 deletions iOS-NOTTODO/iOS-NOTTODO/Network/External/FirebaseUtil.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// FirebaseUtil.swift
// iOS-NOTTODO
//
// Created by 김혜수 on 1/23/24.
//

import Foundation

import FirebaseRemoteConfig

final class FirebaseUtil {

static let shared = FirebaseUtil()

private let config = RemoteConfig.remoteConfig()

enum RemoteConfigType {
case minimumVersion
}

init() {
self.setRemoteConfigSetting()
}

func fetchRemoteConfig(type: RemoteConfigType) async -> String? {
return await withCheckedContinuation { continuation in
config.fetch { [weak self] status, _ in
if status == .success {
self?.config.activate()
guard let version = self?.config["minimum_version"].stringValue, !version.isEmpty else {
continuation.resume(returning: nil)
return
}
continuation.resume(returning: version)
}
}
}
}

private func setRemoteConfigSetting() {
let setting = RemoteConfigSettings()
setting.minimumFetchInterval = 0
setting.fetchTimeout = 10
config.configSettings = setting
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,12 @@ extension AuthViewController {
}

func checkNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
UNUserNotificationCenter.current().getNotificationSettings { [weak self] settings in
switch settings.authorizationStatus {
case .notDetermined:
self.showNotiDialogView()
self?.showNotiDialogView()
default:
break
self?.presentToHomeViewController()
}
}
}
Expand Down
Loading