diff --git a/Runnect-iOS/Podfile.lock b/Runnect-iOS/Podfile.lock index ee6f96e8..78d1280b 100644 --- a/Runnect-iOS/Podfile.lock +++ b/Runnect-iOS/Podfile.lock @@ -637,6 +637,13 @@ PODS: - BoringSSL-GRPC/Interface (0.0.24) - CombineCocoa (0.4.1) - DropDown (2.3.13) + - Firebase/CoreOnly (10.19.0): + - FirebaseCore (= 10.19.0) + - Firebase/RemoteConfig (10.19.0): + - Firebase/CoreOnly + - FirebaseRemoteConfig (~> 10.19.0) + - FirebaseABTesting (10.20.0): + - FirebaseCore (~> 10.0) - FirebaseAnalytics (10.19.0): - FirebaseAnalytics/AdIdSupport (= 10.19.0) - FirebaseCore (~> 10.0) @@ -697,6 +704,13 @@ PODS: - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) + - FirebaseRemoteConfig (10.19.0): + - FirebaseABTesting (~> 10.0) + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - FirebaseSharedSwift (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - "GoogleUtilities/NSData+zlib (~> 7.8)" - FirebaseSharedSwift (10.19.0) - GoogleAppMeasurement (10.19.0): - GoogleAppMeasurement/AdIdSupport (= 10.19.0) @@ -840,6 +854,7 @@ PODS: DEPENDENCIES: - CombineCocoa - DropDown (from `https://github.com/thingineeer/DropDown.git`, commit `95ee36f7bd925d466033c2c169979f1c574bf3b9`) + - Firebase/RemoteConfig - FirebaseAnalytics - FirebaseAuth - FirebaseDynamicLinks @@ -862,6 +877,8 @@ SPEC REPOS: - Alamofire - BoringSSL-GRPC - CombineCocoa + - Firebase + - FirebaseABTesting - FirebaseAnalytics - FirebaseAppCheckInterop - FirebaseAuth @@ -872,6 +889,7 @@ SPEC REPOS: - FirebaseFirestore - FirebaseFirestoreInternal - FirebaseInstallations + - FirebaseRemoteConfig - FirebaseSharedSwift - GoogleAppMeasurement - GoogleUtilities @@ -911,6 +929,8 @@ SPEC CHECKSUMS: BoringSSL-GRPC: 3175b25143e648463a56daeaaa499c6cb86dad33 CombineCocoa: e5210dbfb480ff251078929459ac17e750e7af1d DropDown: bf260fd688978138019ad7d94f63a2362dad85ba + Firebase: 63ce8ece0d43743dc28eacac0c6867a2d7fd5a9d + FirebaseABTesting: 1d5d49804bcfc5fa782bc2491a8c1364e2cf7241 FirebaseAnalytics: 87513010b13b7c8610164d3602ea10571f76afc1 FirebaseAppCheckInterop: 37884781f3e16a1ba47e7ec80a1e805f987788e3 FirebaseAuth: 2492acdcd1245d841fabdf58a050d6aa07dfce3f @@ -921,6 +941,7 @@ SPEC CHECKSUMS: FirebaseFirestore: 9b9b21120c1a0cb4f2789ffb7fbb9138f94c47eb FirebaseFirestoreInternal: a15405fb607dfd14edd568bba77028f4c7a69688 FirebaseInstallations: 033d199474164db20c8350736842a94fe717b960 + FirebaseRemoteConfig: a7fcc7a5941faa7e09248e91c8797340aa4c85f6 FirebaseSharedSwift: f34eeb7d3ea87a34497629b6ca41657beadef76a GoogleAppMeasurement: 68afe759316673c6554dac35a0c7ae8f5d6cb4ed GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34 @@ -944,6 +965,6 @@ SPEC CHECKSUMS: SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25 Then: 844265ae87834bbe1147d91d5d41a404da2ec27d -PODFILE CHECKSUM: 74de7f641476f143613e7b2bfe2c3275248503e4 +PODFILE CHECKSUM: f0cd212e642c1e168379427f2687ba88d51ce3cf -COCOAPODS: 1.14.3 +COCOAPODS: 1.15.0 diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj index a39a9a79..7b28583d 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 232686362B03AF4400675A17 /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232686352B03AF4400675A17 /* NetworkProvider.swift */; }; - 23628DDE2B6BCB9C00894B18 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 23628DDD2B6BCB9C00894B18 /* GoogleService-Info.plist */; }; 23EE06C12AC1AD5200CB3FF8 /* LocationSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C02AC1AD5200CB3FF8 /* LocationSelectView.swift */; }; 23EE06C52AC1AE1900CB3FF8 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C42AC1AE1900CB3FF8 /* BaseView.swift */; }; 23EE06C92AC1DED100CB3FF8 /* GesturePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23EE06C82AC1DED100CB3FF8 /* GesturePublisher.swift */; }; @@ -85,8 +84,6 @@ CE3A53C5296C6017003D518C /* KeychainManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3A53C4296C6017003D518C /* KeychainManager.swift */; }; CE40BB1C2967E4910030ABCA /* RunningWaitingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE40BB1B2967E4910030ABCA /* RunningWaitingVC.swift */; }; CE40BB1E2968054F0030ABCA /* BaseResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE40BB1D2968054F0030ABCA /* BaseResponse.swift */; }; - CE40BB20296805F70030ABCA /* NetworkResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE40BB1F296805F70030ABCA /* NetworkResult.swift */; }; - CE40BB22296806140030ABCA /* NetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE40BB21296806140030ABCA /* NetworkHelper.swift */; }; CE40BB2D296808B00030ABCA /* DepartureSearchingRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE40BB2C296808B00030ABCA /* DepartureSearchingRouter.swift */; }; CE4545C9295D7AF4003201E1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4545C8295D7AF4003201E1 /* AppDelegate.swift */; }; CE4545CB295D7AF4003201E1 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4545CA295D7AF4003201E1 /* SceneDelegate.swift */; }; @@ -181,7 +178,6 @@ /* Begin PBXFileReference section */ 232686352B03AF4400675A17 /* NetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProvider.swift; sourceTree = ""; }; - 23628DDD2B6BCB9C00894B18 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 23EE06C02AC1AD5200CB3FF8 /* LocationSelectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSelectView.swift; sourceTree = ""; }; 23EE06C42AC1AE1900CB3FF8 /* BaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = ""; }; 23EE06C82AC1DED100CB3FF8 /* GesturePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GesturePublisher.swift; sourceTree = ""; }; @@ -266,8 +262,6 @@ CE3A53C4296C6017003D518C /* KeychainManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainManager.swift; sourceTree = ""; }; CE40BB1B2967E4910030ABCA /* RunningWaitingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningWaitingVC.swift; sourceTree = ""; }; CE40BB1D2968054F0030ABCA /* BaseResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseResponse.swift; sourceTree = ""; }; - CE40BB1F296805F70030ABCA /* NetworkResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkResult.swift; sourceTree = ""; }; - CE40BB21296806140030ABCA /* NetworkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkHelper.swift; sourceTree = ""; }; CE40BB2C296808B00030ABCA /* DepartureSearchingRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DepartureSearchingRouter.swift; sourceTree = ""; }; CE4545C5295D7AF4003201E1 /* Runnect-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Runnect-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; CE4545C8295D7AF4003201E1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -1023,8 +1017,6 @@ children = ( CE40BB1D2968054F0030ABCA /* BaseResponse.swift */, CE5875A1296015A2005D967E /* NetworkLoggerPlugin.swift */, - CE40BB1F296805F70030ABCA /* NetworkResult.swift */, - CE40BB21296806140030ABCA /* NetworkHelper.swift */, 712F661C2A7B7BAB00D9539B /* Config.swift */, ); path = Foundation; @@ -1413,7 +1405,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE40BB20296805F70030ABCA /* NetworkResult.swift in Sources */, 715D36E82B2CC64000CAA9D6 /* MyUploadedCourseResponseDto.swift in Sources */, CE55BC11296D4EA600E8CD69 /* RunningRecordRequestDto.swift in Sources */, CE665604295D91B100C64E12 /* makeAlert.swift in Sources */, @@ -1432,7 +1423,6 @@ CE14677829658C7200DCEA1B /* Stopwatch.swift in Sources */, CE21C026299E5FF300F62AF5 /* CourseRouter.swift in Sources */, 23EE06C52AC1AE1900CB3FF8 /* BaseView.swift in Sources */, - CE40BB22296806140030ABCA /* NetworkHelper.swift in Sources */, CE5645162961B72E000A2856 /* ImageLiterals.swift in Sources */, CE4942AD296FCD2300736701 /* UploadedCourseDetailResponseDto.swift in Sources */, CE6655CD295D856300C64E12 /* KeyPathFindable.swift in Sources */, @@ -1711,9 +1701,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOSDebug.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 2024.0122.2217; - DEVELOPMENT_TEAM = 8Q4H7X3Q58; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 8Q4H7X3Q58; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = "Runnect-iOS/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = Runnect; @@ -1734,6 +1726,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.runnect.Runnect-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.runnect.Runnect-iOS"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -1752,9 +1745,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = "Runnect-iOS/Runnect-iOS.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 2024.0122.2217; - DEVELOPMENT_TEAM = 8Q4H7X3Q58; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 8Q4H7X3Q58; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = "Runnect-iOS/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = Runnect; @@ -1775,6 +1770,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.runnect.Runnect-iOS"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.runnect.Runnect-iOS"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme b/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme index 03f5e3ec..911cbe3a 100644 --- a/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme +++ b/Runnect-iOS/Runnect-iOS.xcodeproj/xcshareddata/xcschemes/Runnect-iOS.xcscheme @@ -51,12 +51,6 @@ ReferencedContainer = "container:Runnect-iOS.xcodeproj"> - - - - UIInterfaceOrientationMask { // 세로방향 고정 return UIInterfaceOrientationMask.portrait } - + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() - setRemoteConfig() NMFAuthManager.shared().clientId = Config.naverMapClientId KakaoSDK.initSDK(appKey: Config.kakaoNativeAppKey) return true } - + // MARK: UISceneSession Lifecycle - + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } - + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { // Called when the user discards a scene session. // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } } - -extension AppDelegate { - func setRemoteConfig() { - let remoteConfig = RemoteConfig.remoteConfig() - let settings = RemoteConfigSettings() - - /// 개발 중에는 0으로 설정 - settings.minimumFetchInterval = 86400 // 24hour - remoteConfig.configSettings = settings - - remoteConfig.fetch() { (status, error) -> Void in - if status == .success { - remoteConfig.activate() { (changed, error) in - guard let info = Bundle.main.infoDictionary, - let currentVersion = info["CFBundleShortVersionString"] as? String, - let identifier = info["CFBundleIdentifier"] as? String, - let storeVersion = remoteConfig["iOS_current_market_version"].stringValue - else { return } - - if currentVersion.compare(storeVersion, options: .numeric) == .orderedAscending { - self.showUpdateAlert() - } - } - } else { - print("Error: \(error?.localizedDescription ?? "No error available.")") - } - } - } - - func showUpdateAlert() { - DispatchQueue.main.sync { - let alert = UIAlertController( - title: "업데이트 알림", - message: "새로운 기능이 추가된 'Runnect'의 최신 버전을 만나보세요!\n지금 바로 업데이트하고 개선된 사용자 경험을 즐겨보세요.", - preferredStyle: .alert - ) - - let updateAction = UIAlertAction(title: "업데이트 링크", style: .default) { _ in - let url = "itms-apps://itunes.apple.com/app/1663884202" - if let url = URL(string: url), UIApplication.shared.canOpenURL(url) { - if #available(iOS 13.0, *) { - UIApplication.shared.open(url, options: [:], completionHandler: nil) - } else { - UIApplication.shared.openURL(url) - } - } - } - - alert.addAction(updateAction) - if let vc = UIApplication.shared.keyWindow?.rootViewController { - vc.present(alert, animated: true, completion: nil) - } - } - } -} diff --git a/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkHelper.swift b/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkHelper.swift deleted file mode 100644 index 01305906..00000000 --- a/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkHelper.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// NetworkHelper.swift -// Runnect-iOS -// -// Created by sejin on 2023/01/06. -// - -import Foundation - -import Moya - -struct NetworkHelper { - private init() {} - - // 상태 코드와 데이터, decoding type을 가지고 통신의 결과를 핸들링하는 함수 - static func parseJSON (by statusCode: Int, data: Data, type: T.Type) -> NetworkResult { - let decoder = JSONDecoder() - - guard let decodedData = try? decoder.decode(BaseResponse.self, from: data) else { return .pathErr("pathErr") } - - switch statusCode { - case 200..<300: return .success(decodedData.data as Any) - case 400..<500: return .requestErr(decodedData.data as Any) - case 500..<600: return .serverErr - default: return .networkFail - } - } -} diff --git a/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkResult.swift b/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkResult.swift deleted file mode 100644 index 2990a585..00000000 --- a/Runnect-iOS/Runnect-iOS/Network/Foundation/NetworkResult.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// NetworkResult.swift -// Runnect-iOS -// -// Created by sejin on 2023/01/06. -// - -import Foundation - -enum NetworkResult { - case success(T) // 서버 통신 성공했을 때 - case requestErr(T) // 요청 에러 발생했을 때 - case pathErr(T) // 경로 에러 발생했을 때 - case serverErr // 서버의 내부 에러가 발생했을 때 - case networkFail // 네트워크 연결 실패했을 때 -} diff --git a/Runnect-iOS/Runnect-iOS/Presentation/Splash/VC/SplashVC.swift b/Runnect-iOS/Runnect-iOS/Presentation/Splash/VC/SplashVC.swift index 621e5052..366ee011 100644 --- a/Runnect-iOS/Runnect-iOS/Presentation/Splash/VC/SplashVC.swift +++ b/Runnect-iOS/Runnect-iOS/Presentation/Splash/VC/SplashVC.swift @@ -6,12 +6,18 @@ // import UIKit +import Combine import SnapKit import Then +import FirebaseRemoteConfig final class SplashVC: UIViewController { + // MARK: - Property + + private var cancelBag = CancelBag() + // MARK: - UI Components private let backgroundImageView = UIImageView().then { @@ -31,7 +37,8 @@ final class SplashVC: UIViewController { self.setUI() self.setNavigationBar() self.setLayout() - self.checkDidSignIn() + self.setRemoteConfig() + self.setObserver() } } @@ -92,3 +99,81 @@ extension SplashVC { } } } + +// MARK: - Remote Config + +extension SplashVC { + /// ** RemoteConfig ** + /// 심사버전 > 스토어 버전이면 강제 업데이트 Alert을 진행 합니다. + private func setRemoteConfig() { + let remoteConfig = RemoteConfig.remoteConfig() + let settings = RemoteConfigSettings() + + settings.minimumFetchInterval = 86400 // 개발 중에는 0으로 설정, 실제 앱에서는 적절한 값을 설정 + remoteConfig.configSettings = settings + + remoteConfig.fetch { (status, error) -> Void in + if status == .success { + remoteConfig.activate { (_, _) in + // 현재 앱 버전 가져오기 + guard let info = Bundle.main.infoDictionary, + let currentVersion = info["CFBundleShortVersionString"] as? String, + let storeVersion = remoteConfig["iOS_current_market_version"].stringValue + else { return } + + let splitCurrentVersion = currentVersion.split(separator: ".").map { $0 } + let splitStoreVersion = storeVersion.split(separator: ".").map { $0 } + + if splitCurrentVersion[0] < splitStoreVersion[0] { + // 스토어 버전이 더 높으면 업데이트 필요 + self.showUpdateAlert() + } else { + // 업데이트가 필요하지 않으면 기본 로직 수행 + self.checkDidSignIn() + } + } + } else { + print("Error fetching remote config: \(error?.localizedDescription ?? "No error available.")") + self.checkDidSignIn() + } + } + } + private func showUpdateAlert() { + DispatchQueue.main.async { + let alert = UIAlertController( + title: "업데이트 알림", + message: "새로운 기능이 추가된 'Runnect'의 최신 버전을 만나보세요!\n지금 바로 업데이트하고 개선된 사용자 경험을 즐겨보세요.", + preferredStyle: .alert + ) + + let updateAction = UIAlertAction(title: "업데이트 링크", style: .default) { [self] _ in + self.openAppstore() + } + + alert.addAction(updateAction) + + self.present(alert, animated: false) + + } + } + + private func openAppstore() { + guard let url = URL(string: "itms-apps://itunes.apple.com/app/1663884202") else { return } + + if UIApplication.shared.canOpenURL(url) { + if #available(iOS 13.0, *) { + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } else { + UIApplication.shared.openURL(url) + } + } + } + + private func setObserver() { + NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification) + .sink { [weak self] _ in + self?.setRemoteConfig() + } + .store(in: cancelBag) + } +} diff --git a/Runnect-iOS/fastlane/Matchfile b/Runnect-iOS/fastlane/Matchfile index 34e6e9f3..55ed04f7 100644 --- a/Runnect-iOS/fastlane/Matchfile +++ b/Runnect-iOS/fastlane/Matchfile @@ -1,10 +1,10 @@ -git_url("https://github.com/thingineeer/fastlane-match") -git_branch("Runnect") # 'Runnect' 앱을 위한 인증서 관리를 할 브랜치 +git_url("https://github.com/thingineeer/fastlane-match-runnect") +# git_branch("Runnect") 수정 금지 storage_mode("git") type("development") # The default type, can be: appstore, adhoc, enterprise or development -# app_identifier(["tools.fastlane.app", "tools.fastlane.app2"]) +# app_identifier("com.runnect.Runnect-iOS") # username("user@fastlane.tools") # Your Apple Developer Portal username # For all available options run `fastlane match --help`