diff --git a/README.md b/README.md index 46001ff..31c292d 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ ## 앱아이콘 -## 앱 UI + +## 앱 UI + ## 토스 코인앱은 어떤건가요?? @@ -30,8 +32,14 @@ ## 팀원 소개 - - +IOS 메인 개발: [로이](https://github.com/Roy-wonji)
+IOS 개발 및 PM : [성형](https://github.com/seonghyeonOrNot)
+IOS 개발 : [승용](https://github.com/KSYong) + +## 앱스토어 +## App stroe +Download on the App Store + ## 사용한 라이브러리 diff --git a/StockApp/Firebase/GoogleService-Info.plist b/StockApp/Firebase/GoogleService-Info.plist index 6dae6a4..827f822 100644 --- a/StockApp/Firebase/GoogleService-Info.plist +++ b/StockApp/Firebase/GoogleService-Info.plist @@ -3,9 +3,9 @@ CLIENT_ID - 1060378286730-d080s67ukoj1bll1ejs0bu154mbna1j7.apps.googleusercontent.com + 1060378286730-29djldpanil8cgbcgqnrh8dt4b751042.apps.googleusercontent.com REVERSED_CLIENT_ID - com.googleusercontent.apps.1060378286730-d080s67ukoj1bll1ejs0bu154mbna1j7 + com.googleusercontent.apps.1060378286730-29djldpanil8cgbcgqnrh8dt4b751042 API_KEY AIzaSyBdwoezq_Q99fpdGb5F7V-T0f24iPKCqYE GCM_SENDER_ID @@ -13,22 +13,22 @@ PLIST_VERSION 1 BUNDLE_ID - Roy.com.StockApp + Roy.com.CoinMoya PROJECT_ID coinmoya-d0b4b STORAGE_BUCKET coinmoya-d0b4b.appspot.com IS_ADS_ENABLED - + IS_ANALYTICS_ENABLED - + IS_APPINVITE_ENABLED - + IS_GCM_ENABLED - + IS_SIGNIN_ENABLED - + GOOGLE_APP_ID - 1:1060378286730:ios:526ec0d6b72e4fe6c3ab73 + 1:1060378286730:ios:b461c7c0405a684bc3ab73 - + \ No newline at end of file diff --git a/StockApp/StockApp.xcodeproj/project.pbxproj b/StockApp/StockApp.xcodeproj/project.pbxproj index 3ac3293..7169251 100644 --- a/StockApp/StockApp.xcodeproj/project.pbxproj +++ b/StockApp/StockApp.xcodeproj/project.pbxproj @@ -7,7 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 532A4A86558635120E7072C1 /* Pods_StockAppTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4315C1EB8177A7D4FCD224E /* Pods_StockAppTests.framework */; }; + 41190DA09DB7F8906F173EB9 /* Pods_StockApp_StockAppUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F32E6C64CF278276E847CC5F /* Pods_StockApp_StockAppUITests.framework */; }; + 60FABEEC29536123007EEFC6 /* CustomDisabledInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60FABEEB29536123007EEFC6 /* CustomDisabledInputField.swift */; }; 7F01DFB628F70068000ECB96 /* AuthorizationVIewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F01DFB528F70068000ECB96 /* AuthorizationVIewModel.swift */; }; 7F01DFBA28F70961000ECB96 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F01DFB928F70961000ECB96 /* AppDelegate.swift */; }; 7F02A5FE28E7316E00F4B56C /* CryptoDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F02A5FD28E7316E00F4B56C /* CryptoDetailView.swift */; }; @@ -40,6 +41,7 @@ 7F2382C528DEB39C00103AE7 /* APIKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2382C428DEB39C00103AE7 /* APIKey.swift */; }; 7F29425628F31C4D00A44CDD /* RoundShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F29425528F31C4D00A44CDD /* RoundShape.swift */; }; 7F29425928F329A400A44CDD /* ModalShapeCorner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F29425828F329A400A44CDD /* ModalShapeCorner.swift */; }; + 7F2AD631299207B3004DB28B /* withDrawPOPUPView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2AD630299207B3004DB28B /* withDrawPOPUPView.swift */; }; 7F2AEB4128E8395D00FA86AD /* CryptoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2AEB4028E8395C00FA86AD /* CryptoDetailViewModel.swift */; }; 7F2AEB4328E839D900FA86AD /* CryptoDetailModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2AEB4228E839D900FA86AD /* CryptoDetailModel.swift */; }; 7F2AEB4528E83E0500FA86AD /* CoinDetailSetvice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F2AEB4428E83E0500FA86AD /* CoinDetailSetvice.swift */; }; @@ -123,12 +125,12 @@ 7FB1AC94291D497300A0B67C /* ProfileEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB1AC93291D497300A0B67C /* ProfileEditView.swift */; }; 7FB1AC96291E798A00A0B67C /* ProfileEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB1AC95291E798A00A0B67C /* ProfileEditViewModel.swift */; }; 7FB1AC98291E7FB400A0B67C /* FeedBackViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB1AC97291E7FB400A0B67C /* FeedBackViewModel.swift */; }; + 7FB26362294CA6FD002349DB /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FB26361294CA6FD002349DB /* UserModel.swift */; }; 7FBA185F28F7135100025001 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 7FBA185E28F7135100025001 /* FirebaseAuth */; }; 7FBA186128F7135100025001 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 7FBA186028F7135100025001 /* FirebaseFirestore */; }; 7FBA186328F7135100025001 /* FirebaseFirestoreSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7FBA186228F7135100025001 /* FirebaseFirestoreSwift */; }; 7FBA186528F7135100025001 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = 7FBA186428F7135100025001 /* FirebaseStorage */; }; 7FBB004829226EF7002380B7 /* UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB004729226EF7002380B7 /* UserService.swift */; }; - 7FBB004B29227897002380B7 /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB004A29227897002380B7 /* UserModel.swift */; }; 7FBB004D29229543002380B7 /* ProfileNotice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB004C29229543002380B7 /* ProfileNotice.swift */; }; 7FBB004F292295C7002380B7 /* MyProfileEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB004E292295C7002380B7 /* MyProfileEditView.swift */; }; 7FBB005129229906002380B7 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FBB005029229906002380B7 /* SettingView.swift */; }; @@ -145,6 +147,7 @@ 7FC3564D28D8C3C9002E0E63 /* CircleButtonAnimationVIew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FC3564C28D8C3C9002E0E63 /* CircleButtonAnimationVIew.swift */; }; 7FCD241428FAEF30002C5C18 /* ErroAlertMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCD241328FAEF30002C5C18 /* ErroAlertMessage.swift */; }; 7FCD241628FBC5F5002C5C18 /* SnsLoginDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FCD241528FBC5F5002C5C18 /* SnsLoginDelegate.swift */; }; + 7FD08F4A295FCC7500ED04CE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7F66CCC8295FBD6400FA930F /* GoogleService-Info.plist */; }; 7FD9E45628F40FF8003528D4 /* SNSLoginManger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FD9E45528F40FF8003528D4 /* SNSLoginManger.swift */; }; 7FE7929F28FD81A900E3D6E3 /* TweetRowVIew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FE7929E28FD81A900E3D6E3 /* TweetRowVIew.swift */; }; 7FE792A128FD81BE00E3D6E3 /* FeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FE792A028FD81BE00E3D6E3 /* FeedView.swift */; }; @@ -192,20 +195,17 @@ 7FF3BF542904474900ED0B81 /* ListRowTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF3BF532904474900ED0B81 /* ListRowTextView.swift */; }; 7FF3BF5629044B7600ED0B81 /* ListRowSystemImageTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF3BF5529044B7600ED0B81 /* ListRowSystemImageTextView.swift */; }; 7FF4835A28E51DC2004DEC37 /* SortOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FF4835928E51DC2004DEC37 /* SortOption.swift */; }; - 7FFC3CCC2944546A004FD061 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7FFC3CC72944428C004FD061 /* GoogleService-Info.plist */; }; 7FFC3CD129446630004FD061 /* AccountManageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFC3CD029446630004FD061 /* AccountManageViewModel.swift */; }; 7FFC3CD5294467AA004FD061 /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFC3CD4294467AA004FD061 /* ImagePicker.swift */; }; 7FFC3CD829446ABD004FD061 /* ImageUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFC3CD729446ABD004FD061 /* ImageUploader.swift */; }; - 7FFC3D0E29449E05004FD061 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7FFC3CC72944428C004FD061 /* GoogleService-Info.plist */; }; - 7FFC3D0F29449E0F004FD061 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7FFC3CC72944428C004FD061 /* GoogleService-Info.plist */; }; 7FFFD5AD2928BD1200A25207 /* StockAPI-Stock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5AC2928BD1200A25207 /* StockAPI-Stock.swift */; }; 7FFFD5AF292A36AA00A25207 /* StockConvertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5AE292A36AA00A25207 /* StockConvertViewModel.swift */; }; 7FFFD5B1292A3D6A00A25207 /* StockRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5B0292A3D6A00A25207 /* StockRowView.swift */; }; 7FFFD5B7292A523D00A25207 /* StockViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5B6292A523D00A25207 /* StockViewModel.swift */; }; 7FFFD5B9292A58C900A25207 /* ScrollViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5B8292A58C900A25207 /* ScrollViewModifier.swift */; }; 7FFFD5BB292A701700A25207 /* StockTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FFFD5BA292A701700A25207 /* StockTabBarButton.swift */; }; - C52F1CF3B01E3F32F9D34B34 /* Pods_StockApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4379C3850A4B3CB11556B30 /* Pods_StockApp.framework */; }; - E5A63961077A7A301B7C60FA /* Pods_StockApp_StockAppUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0767B52749F12C54F4643BDE /* Pods_StockApp_StockAppUITests.framework */; }; + B3463BDEBD4EF6B09D09E992 /* Pods_StockAppTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B2490BF17AD4DD05A87AF04 /* Pods_StockAppTests.framework */; }; + D428C5485F7DFE197642DD92 /* Pods_StockApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F518824CCDFAF81ABDFD83E2 /* Pods_StockApp.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -238,11 +238,11 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0767B52749F12C54F4643BDE /* Pods_StockApp_StockAppUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockApp_StockAppUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C9B884634B528D7E75182FA /* Pods-StockApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp.debug.xcconfig"; path = "Target Support Files/Pods-StockApp/Pods-StockApp.debug.xcconfig"; sourceTree = ""; }; - 165FFC9211C79A8DE8904D6E /* Pods-StockApp-StockAppUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp-StockAppUITests.debug.xcconfig"; path = "Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests.debug.xcconfig"; sourceTree = ""; }; - 6CB14FC76BB1C744011FED7C /* Pods-StockAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockAppTests.release.xcconfig"; path = "Target Support Files/Pods-StockAppTests/Pods-StockAppTests.release.xcconfig"; sourceTree = ""; }; - 7D23965C93E51F805801B6EA /* Pods-StockApp-StockAppUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp-StockAppUITests.release.xcconfig"; path = "Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests.release.xcconfig"; sourceTree = ""; }; + 0A9C39889FC55D51A0332551 /* Pods-StockAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockAppTests.debug.xcconfig"; path = "Target Support Files/Pods-StockAppTests/Pods-StockAppTests.debug.xcconfig"; sourceTree = ""; }; + 0D3B0D33ED831495F84ACE87 /* Pods-StockApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp.release.xcconfig"; path = "Target Support Files/Pods-StockApp/Pods-StockApp.release.xcconfig"; sourceTree = ""; }; + 2519109A32E05759C770FF92 /* Pods-StockApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp.debug.xcconfig"; path = "Target Support Files/Pods-StockApp/Pods-StockApp.debug.xcconfig"; sourceTree = ""; }; + 60FABEEB29536123007EEFC6 /* CustomDisabledInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDisabledInputField.swift; sourceTree = ""; }; + 6B2490BF17AD4DD05A87AF04 /* Pods_StockAppTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockAppTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7F01DFB528F70068000ECB96 /* AuthorizationVIewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationVIewModel.swift; sourceTree = ""; }; 7F01DFB928F70961000ECB96 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7F02A5FD28E7316E00F4B56C /* CryptoDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoDetailView.swift; sourceTree = ""; }; @@ -270,6 +270,7 @@ 7F2382C428DEB39C00103AE7 /* APIKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIKey.swift; sourceTree = ""; }; 7F29425528F31C4D00A44CDD /* RoundShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundShape.swift; sourceTree = ""; }; 7F29425828F329A400A44CDD /* ModalShapeCorner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalShapeCorner.swift; sourceTree = ""; }; + 7F2AD630299207B3004DB28B /* withDrawPOPUPView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = withDrawPOPUPView.swift; sourceTree = ""; }; 7F2AEB4028E8395C00FA86AD /* CryptoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoDetailViewModel.swift; sourceTree = ""; }; 7F2AEB4228E839D900FA86AD /* CryptoDetailModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoDetailModel.swift; sourceTree = ""; }; 7F2AEB4428E83E0500FA86AD /* CoinDetailSetvice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoinDetailSetvice.swift; sourceTree = ""; }; @@ -312,6 +313,7 @@ 7F4EBEA9293B842800ED053F /* MockTickerListRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockTickerListRepository.swift; sourceTree = ""; }; 7F54F5E6292E531600D97AAF /* StockSymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StockSymbol.swift; sourceTree = ""; }; 7F5A70422943927900453EAA /* ReadyPopUPview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadyPopUPview.swift; sourceTree = ""; }; + 7F66CCC8295FBD6400FA930F /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 7F6910122915497E00BE9A3F /* LanchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanchView.swift; sourceTree = ""; }; 7F6B32422944C3DF0008FF1A /* ProfilViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilViewModel.swift; sourceTree = ""; }; 7F6B32452944C43C0008FF1A /* AppManger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManger.swift; sourceTree = ""; }; @@ -352,8 +354,8 @@ 7FB1AC93291D497300A0B67C /* ProfileEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditView.swift; sourceTree = ""; }; 7FB1AC95291E798A00A0B67C /* ProfileEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditViewModel.swift; sourceTree = ""; }; 7FB1AC97291E7FB400A0B67C /* FeedBackViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedBackViewModel.swift; sourceTree = ""; }; + 7FB26361294CA6FD002349DB /* UserModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = UserModel.swift; path = StockApp/View/MyProfile/UserModel.swift; sourceTree = SOURCE_ROOT; }; 7FBB004729226EF7002380B7 /* UserService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserService.swift; sourceTree = ""; }; - 7FBB004A29227897002380B7 /* UserModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserModel.swift; sourceTree = ""; }; 7FBB004C29229543002380B7 /* ProfileNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileNotice.swift; sourceTree = ""; }; 7FBB004E292295C7002380B7 /* MyProfileEditView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyProfileEditView.swift; sourceTree = ""; }; 7FBB005029229906002380B7 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = ""; }; @@ -368,7 +370,6 @@ 7FC3564528D8B0EC002E0E63 /* AddMainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMainView.swift; sourceTree = ""; }; 7FC3564A28D8B4CF002E0E63 /* CircleButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleButtonView.swift; sourceTree = ""; }; 7FC3564C28D8C3C9002E0E63 /* CircleButtonAnimationVIew.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleButtonAnimationVIew.swift; sourceTree = ""; }; - 7FCD240F28FAE031002C5C18 /* StockApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = StockApp.entitlements; sourceTree = ""; }; 7FCD241328FAEF30002C5C18 /* ErroAlertMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErroAlertMessage.swift; sourceTree = ""; }; 7FCD241528FBC5F5002C5C18 /* SnsLoginDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnsLoginDelegate.swift; sourceTree = ""; }; 7FD9E45528F40FF8003528D4 /* SNSLoginManger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SNSLoginManger.swift; sourceTree = ""; }; @@ -426,7 +427,6 @@ 7FFC3CC32943A520004FD061 /* ci_post_clone.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_post_clone.sh; sourceTree = ""; }; 7FFC3CC42943A534004FD061 /* ci_pre_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_pre_xcodebuild.sh; sourceTree = ""; }; 7FFC3CC52943A546004FD061 /* ci_post_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_post_xcodebuild.sh; sourceTree = ""; }; - 7FFC3CC72944428C004FD061 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 7FFC3CD029446630004FD061 /* AccountManageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountManageViewModel.swift; sourceTree = ""; }; 7FFC3CD4294467AA004FD061 /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = ""; }; 7FFC3CD729446ABD004FD061 /* ImageUploader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageUploader.swift; sourceTree = ""; }; @@ -436,10 +436,11 @@ 7FFFD5B6292A523D00A25207 /* StockViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StockViewModel.swift; sourceTree = ""; }; 7FFFD5B8292A58C900A25207 /* ScrollViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewModifier.swift; sourceTree = ""; }; 7FFFD5BA292A701700A25207 /* StockTabBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StockTabBarButton.swift; sourceTree = ""; }; - 952411984CAC3120E22BFF1F /* Pods-StockAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockAppTests.debug.xcconfig"; path = "Target Support Files/Pods-StockAppTests/Pods-StockAppTests.debug.xcconfig"; sourceTree = ""; }; - B4315C1EB8177A7D4FCD224E /* Pods_StockAppTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockAppTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CE51E0D87FBE5660AF6FF218 /* Pods-StockApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp.release.xcconfig"; path = "Target Support Files/Pods-StockApp/Pods-StockApp.release.xcconfig"; sourceTree = ""; }; - E4379C3850A4B3CB11556B30 /* Pods_StockApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 87844FB9D1EFF7706DB196F2 /* Pods-StockApp-StockAppUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp-StockAppUITests.release.xcconfig"; path = "Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests.release.xcconfig"; sourceTree = ""; }; + CC7943DDBA7996F5DB766F31 /* Pods-StockAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockAppTests.release.xcconfig"; path = "Target Support Files/Pods-StockAppTests/Pods-StockAppTests.release.xcconfig"; sourceTree = ""; }; + D8C5D58B49420E55F813AD43 /* Pods-StockApp-StockAppUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StockApp-StockAppUITests.debug.xcconfig"; path = "Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests.debug.xcconfig"; sourceTree = ""; }; + F32E6C64CF278276E847CC5F /* Pods_StockApp_StockAppUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockApp_StockAppUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F518824CCDFAF81ABDFD83E2 /* Pods_StockApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StockApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -456,7 +457,7 @@ 7FBA186528F7135100025001 /* FirebaseStorage in Frameworks */, 7FBA186328F7135100025001 /* FirebaseFirestoreSwift in Frameworks */, 7FF3BF4229040BC600ED0B81 /* GoogleSignIn in Frameworks */, - C52F1CF3B01E3F32F9D34B34 /* Pods_StockApp.framework in Frameworks */, + D428C5485F7DFE197642DD92 /* Pods_StockApp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -464,7 +465,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 532A4A86558635120E7072C1 /* Pods_StockAppTests.framework in Frameworks */, + B3463BDEBD4EF6B09D09E992 /* Pods_StockAppTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -472,13 +473,22 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E5A63961077A7A301B7C60FA /* Pods_StockApp_StockAppUITests.framework in Frameworks */, + 41190DA09DB7F8906F173EB9 /* Pods_StockApp_StockAppUITests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 6095990129502030000AF865 /* ImageManager */ = { + isa = PBXGroup; + children = ( + 7FFC3CD729446ABD004FD061 /* ImageUploader.swift */, + 7FFC3CD4294467AA004FD061 /* ImagePicker.swift */, + ); + path = ImageManager; + sourceTree = ""; + }; 7F02A5FB28E730A400F4B56C /* CryptoDetail */ = { isa = PBXGroup; children = ( @@ -518,6 +528,7 @@ 7F15F76B290582B400B06452 /* PopupView.swift */, 7F4E82DD2909809B00B65D97 /* SignupPopupVIew.swift */, 7F5A70422943927900453EAA /* ReadyPopUPview.swift */, + 7F2AD630299207B3004DB28B /* withDrawPOPUPView.swift */, ); path = POPUP; sourceTree = ""; @@ -527,6 +538,7 @@ children = ( 7F174E7028F587D200352189 /* CustomInputField.swift */, 7F174E7228F58DF900352189 /* CustomSecureInputField.swift */, + 60FABEEB29536123007EEFC6 /* CustomDisabledInputField.swift */, ); path = TextField; sourceTree = ""; @@ -749,12 +761,12 @@ path = WebView; sourceTree = ""; }; - 7FBB00492922787A002380B7 /* User */ = { + 7FBB00492922787A002380B7 /* UserModel */ = { isa = PBXGroup; children = ( - 7FBB004A29227897002380B7 /* UserModel.swift */, + 7FB26361294CA6FD002349DB /* UserModel.swift */, ); - path = User; + path = UserModel; sourceTree = ""; }; 7FBB00522923C0EC002380B7 /* Error */ = { @@ -959,7 +971,7 @@ 7FE836FB28BF95B7003761FE /* StockAppUITests */, 7FE836DF28BF95B0003761FE /* Products */, E8D1B2D0E67DC5DBB1C3A836 /* Pods */, - 89C74444663A84CFC3B76A18 /* Frameworks */, + F3A7DB021E4412F2548FE36A /* Frameworks */, ); sourceTree = ""; }; @@ -976,7 +988,6 @@ 7FE836E028BF95B0003761FE /* StockApp */ = { isa = PBXGroup; children = ( - 7FCD240F28FAE031002C5C18 /* StockApp.entitlements */, 7FE8372128BF9CBD003761FE /* Info.plist */, 7FE8370B28BF966F003761FE /* Application */, 7FE8370C28BF9681003761FE /* Utills */, @@ -1029,9 +1040,8 @@ 7FE8370C28BF9681003761FE /* Utills */ = { isa = PBXGroup; children = ( + 6095990129502030000AF865 /* ImageManager */, 7F6B32442944C42B0008FF1A /* AppManger */, - 7FFC3CD629446AA5004FD061 /* ImageUploaders */, - 7FFC3CD329446718004FD061 /* ImagePickers */, 7F94E5F62937A4F0001F5F0D /* AppCheck */, 7FF3BF3B290405C800ED0B81 /* View */, 7FED2A6D28FA5C8E00D7A7C7 /* ViewRouter */, @@ -1048,7 +1058,7 @@ 7FE8370D28BF9699003761FE /* Model */ = { isa = PBXGroup; children = ( - 7FBB00492922787A002380B7 /* User */, + 7FBB00492922787A002380B7 /* UserModel */, 7FFEF7C828EF08DB0023AACC /* StockModel */, 7F729ED828D9FFC100FEAE43 /* CryptoModel */, ); @@ -1277,7 +1287,7 @@ 7FFC3CC62944427F004FD061 /* Firebase */ = { isa = PBXGroup; children = ( - 7FFC3CC72944428C004FD061 /* GoogleService-Info.plist */, + 7F66CCC8295FBD6400FA930F /* GoogleService-Info.plist */, ); path = Firebase; sourceTree = ""; @@ -1290,22 +1300,6 @@ path = AccountManageViewModel.; sourceTree = ""; }; - 7FFC3CD329446718004FD061 /* ImagePickers */ = { - isa = PBXGroup; - children = ( - 7FFC3CD4294467AA004FD061 /* ImagePicker.swift */, - ); - path = ImagePickers; - sourceTree = ""; - }; - 7FFC3CD629446AA5004FD061 /* ImageUploaders */ = { - isa = PBXGroup; - children = ( - 7FFC3CD729446ABD004FD061 /* ImageUploader.swift */, - ); - path = ImageUploaders; - sourceTree = ""; - }; 7FFEF7C828EF08DB0023AACC /* StockModel */ = { isa = PBXGroup; children = ( @@ -1320,27 +1314,27 @@ path = StockModel; sourceTree = ""; }; - 89C74444663A84CFC3B76A18 /* Frameworks */ = { + E8D1B2D0E67DC5DBB1C3A836 /* Pods */ = { isa = PBXGroup; children = ( - E4379C3850A4B3CB11556B30 /* Pods_StockApp.framework */, - 0767B52749F12C54F4643BDE /* Pods_StockApp_StockAppUITests.framework */, - B4315C1EB8177A7D4FCD224E /* Pods_StockAppTests.framework */, + 2519109A32E05759C770FF92 /* Pods-StockApp.debug.xcconfig */, + 0D3B0D33ED831495F84ACE87 /* Pods-StockApp.release.xcconfig */, + D8C5D58B49420E55F813AD43 /* Pods-StockApp-StockAppUITests.debug.xcconfig */, + 87844FB9D1EFF7706DB196F2 /* Pods-StockApp-StockAppUITests.release.xcconfig */, + 0A9C39889FC55D51A0332551 /* Pods-StockAppTests.debug.xcconfig */, + CC7943DDBA7996F5DB766F31 /* Pods-StockAppTests.release.xcconfig */, ); - name = Frameworks; + path = Pods; sourceTree = ""; }; - E8D1B2D0E67DC5DBB1C3A836 /* Pods */ = { + F3A7DB021E4412F2548FE36A /* Frameworks */ = { isa = PBXGroup; children = ( - 0C9B884634B528D7E75182FA /* Pods-StockApp.debug.xcconfig */, - CE51E0D87FBE5660AF6FF218 /* Pods-StockApp.release.xcconfig */, - 165FFC9211C79A8DE8904D6E /* Pods-StockApp-StockAppUITests.debug.xcconfig */, - 7D23965C93E51F805801B6EA /* Pods-StockApp-StockAppUITests.release.xcconfig */, - 952411984CAC3120E22BFF1F /* Pods-StockAppTests.debug.xcconfig */, - 6CB14FC76BB1C744011FED7C /* Pods-StockAppTests.release.xcconfig */, + F518824CCDFAF81ABDFD83E2 /* Pods_StockApp.framework */, + F32E6C64CF278276E847CC5F /* Pods_StockApp_StockAppUITests.framework */, + 6B2490BF17AD4DD05A87AF04 /* Pods_StockAppTests.framework */, ); - path = Pods; + name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ @@ -1350,15 +1344,14 @@ isa = PBXNativeTarget; buildConfigurationList = 7FE8370228BF95B7003761FE /* Build configuration list for PBXNativeTarget "StockApp" */; buildPhases = ( - D7114E9DEBA594589491069B /* [CP] Check Pods Manifest.lock */, + 3C8B11546A13B065B51F38FF /* [CP] Check Pods Manifest.lock */, 7FE836DA28BF95B0003761FE /* Sources */, 7FE836DB28BF95B0003761FE /* Frameworks */, 7FE836DC28BF95B0003761FE /* Resources */, 7FE8371628BF9800003761FE /* ShellScript */, - 7FFC3CC9294445CC004FD061 /* Firebase Script */, 7FFC3CCA29444C0A004FD061 /* CopyFiles */, - F5EC6833BFE1D16F5F19A283 /* [CP] Embed Pods Frameworks */, 7F6B32502944FD470008FF1A /* Firebase Crsashlytics */, + D95702BD8ABEB152F7F210A6 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -1384,7 +1377,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7FE8370528BF95B7003761FE /* Build configuration list for PBXNativeTarget "StockAppTests" */; buildPhases = ( - A54A8DE056979144ADF24F10 /* [CP] Check Pods Manifest.lock */, + D5E4CA087F7EE6597CBAEB6B /* [CP] Check Pods Manifest.lock */, 7FE836EA28BF95B7003761FE /* Sources */, 7FE836EB28BF95B7003761FE /* Frameworks */, 7FE836EC28BF95B7003761FE /* Resources */, @@ -1403,12 +1396,12 @@ isa = PBXNativeTarget; buildConfigurationList = 7FE8370828BF95B7003761FE /* Build configuration list for PBXNativeTarget "StockAppUITests" */; buildPhases = ( - D8DD57784B901C423A792AE5 /* [CP] Check Pods Manifest.lock */, + 75B43724F6872A7375F96AB0 /* [CP] Check Pods Manifest.lock */, 7FE836F428BF95B7003761FE /* Sources */, 7FE836F528BF95B7003761FE /* Frameworks */, 7FE836F628BF95B7003761FE /* Resources */, 7FFC3CC82944429F004FD061 /* ShellScript */, - 5D0873DD61D36F06B70BEEEA /* [CP] Embed Pods Frameworks */, + 81227077A7D64464740ABF0C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -1428,7 +1421,7 @@ attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1340; + LastUpgradeCheck = 1420; TargetAttributes = { 7FE836DD28BF95B0003761FE = { CreatedOnToolsVersion = 13.4.1; @@ -1445,12 +1438,11 @@ }; buildConfigurationList = 7FE836D928BF95B0003761FE /* Build configuration list for PBXProject "StockApp" */; compatibilityVersion = "Xcode 13.0"; - developmentRegion = en; + developmentRegion = ko; hasScannedForEncodings = 0; knownRegions = ( - en, - Base, ko, + Base, ); mainGroup = 7FE836D528BF95B0003761FE; packageReferences = ( @@ -1476,7 +1468,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7FFC3CCC2944546A004FD061 /* GoogleService-Info.plist in Resources */, + 7FD08F4A295FCC7500ED04CE /* GoogleService-Info.plist in Resources */, 7F1C8EDD28BFA787004E49A1 /* SpoqaHanSansNeo-Bold.ttf in Resources */, 7F98D136290568580088A052 /* 나눔손글씨 맛있는체.ttf in Resources */, 7F1C8EDE28BFA787004E49A1 /* SpoqaHanSansNeo-Light.ttf in Resources */, @@ -1494,7 +1486,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7FFC3D0E29449E05004FD061 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1502,31 +1493,13 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7FFC3D0F29449E0F004FD061 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 5D0873DD61D36F06B70BEEEA /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 7F6B32502944FD470008FF1A /* Firebase Crsashlytics */ = { + 3C8B11546A13B065B51F38FF /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1534,37 +1507,43 @@ inputFileListPaths = ( ); inputPaths = ( - "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}", - "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "Firebase Crsashlytics"; + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-StockApp-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 7FE8371628BF9800003761FE /* ShellScript */ = { + 75B43724F6872A7375F96AB0 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - buildActionMask = 8; + buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-StockApp-StockAppUITests-checkManifestLockResult.txt", ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nexport PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 7FFC3CC82944429F004FD061 /* ShellScript */ = { + 7F6B32502944FD470008FF1A /* Firebase Crsashlytics */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1572,17 +1551,19 @@ inputFileListPaths = ( ); inputPaths = ( + "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}", + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", ); + name = "Firebase Crsashlytics"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nif [ \"$CONFIGURATION\" = \"release\" ]; then\nprintf \"creating release configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nelse \nprintf \"creating dev configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nfi\n"; - showEnvVarsInLog = 0; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\n"; }; - 7FFC3CC9294445CC004FD061 /* Firebase Script */ = { + 7FE8371628BF9800003761FE /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 8; files = ( @@ -1591,16 +1572,16 @@ ); inputPaths = ( ); - name = "Firebase Script"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nif [ \"$CONFIGURATION\" = \"release\" ]; then\nprintf \"creating release configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nelse \nprintf \"creating dev configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nfi\n"; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nexport PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + showEnvVarsInLog = 0; }; - A54A8DE056979144ADF24F10 /* [CP] Check Pods Manifest.lock */ = { + 7FFC3CC82944429F004FD061 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1608,43 +1589,34 @@ inputFileListPaths = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-StockAppTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nif [ \"$CONFIGURATION\" = \"release\" ]; then\nprintf \"creating release configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nelse \nprintf \"creating dev configuration\";\ncp -r \"$PROJECT_DIR/Firebase/GoogleService-Info.plist\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist\"\nfi\n"; showEnvVarsInLog = 0; }; - D7114E9DEBA594589491069B /* [CP] Check Pods Manifest.lock */ = { + 81227077A7D64464740ABF0C /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-StockApp-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-StockApp-StockAppUITests/Pods-StockApp-StockAppUITests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - D8DD57784B901C423A792AE5 /* [CP] Check Pods Manifest.lock */ = { + D5E4CA087F7EE6597CBAEB6B /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1659,14 +1631,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-StockApp-StockAppUITests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-StockAppTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F5EC6833BFE1D16F5F19A283 /* [CP] Embed Pods Frameworks */ = { + D95702BD8ABEB152F7F210A6 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1706,6 +1678,7 @@ 7F2382C028DDEC4E00103AE7 /* CoinDataService.swift in Sources */, 7F729EE328DB533600FEAE43 /* CoinViewModel.swift in Sources */, 7F4EBEA8293B7CA400ED053F /* TickerListRepository.swift in Sources */, + 60FABEEC29536123007EEFC6 /* CustomDisabledInputField.swift in Sources */, 7FBB00592923CE4A002380B7 /* Agent.swift in Sources */, 7FFC3CD5294467AA004FD061 /* ImagePicker.swift in Sources */, 7FFFD5B9292A58C900A25207 /* ScrollViewModifier.swift in Sources */, @@ -1724,6 +1697,7 @@ 7FFC3CD829446ABD004FD061 /* ImageUploader.swift in Sources */, 7F94E5FF2938CA7D001F5F0D /* MockStockAPI.swift in Sources */, 7FEE221B28FC670100792003 /* TweetFilterViewModel.swift in Sources */, + 7FB26362294CA6FD002349DB /* UserModel.swift in Sources */, 7FC3563A28D8A221002E0E63 /* CryptoMainView.swift in Sources */, 7FEF4F9E28E0809E00DA9AEB /* UIApplication.swift in Sources */, 7F8B65902934E6E200C5203D /* EmptyStateView.swift in Sources */, @@ -1773,6 +1747,7 @@ 7FBB004F292295C7002380B7 /* MyProfileEditView.swift in Sources */, 7F8B65AC2936455300C5203D /* StockSearchView.swift in Sources */, 7FB1AC98291E7FB400A0B67C /* FeedBackViewModel.swift in Sources */, + 7F2AD631299207B3004DB28B /* withDrawPOPUPView.swift in Sources */, 7F06912128CB14E3005F840E /* NetworkManger.swift in Sources */, 7F6910132915497E00BE9A3F /* LanchView.swift in Sources */, 7F15F76C290582B400B06452 /* PopupView.swift in Sources */, @@ -1800,7 +1775,6 @@ 7F729EE128DB3F6400FEAE43 /* Foundation+Extensions.swift in Sources */, 7F29425928F329A400A44CDD /* ModalShapeCorner.swift in Sources */, 7FED2A7128FA5ED800D7A7C7 /* UserDefaults.swift in Sources */, - 7FBB004B29227897002380B7 /* UserModel.swift in Sources */, 7F8B658B2934DC2500C5203D /* TickerListRowData.swift in Sources */, 7FF3BF5629044B7600ED0B81 /* ListRowSystemImageTextView.swift in Sources */, 7F4E82DE2909809B00B65D97 /* SignupPopupVIew.swift in Sources */, @@ -1901,6 +1875,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -1961,6 +1936,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; @@ -2013,13 +1989,13 @@ }; 7FE8370328BF95B7003761FE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C9B884634B528D7E75182FA /* Pods-StockApp.debug.xcconfig */; + baseConfigurationReference = 2519109A32E05759C770FF92 /* Pods-StockApp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = StockApp/StockApp.entitlements; + CODE_SIGN_ENTITLEMENTS = StockApp/StockAppDebug.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 20; + CURRENT_PROJECT_VERSION = 18; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"StockApp/Preview Content\""; DEVELOPMENT_TEAM = N94CS4N6VR; @@ -2041,8 +2017,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockApp; + MARKETING_VERSION = 1.0.2; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -2055,13 +2031,14 @@ }; 7FE8370428BF95B7003761FE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CE51E0D87FBE5660AF6FF218 /* Pods-StockApp.release.xcconfig */; + baseConfigurationReference = 0D3B0D33ED831495F84ACE87 /* Pods-StockApp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = StockApp/StockApp.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 20; + CURRENT_PROJECT_VERSION = 18; DEVELOPMENT_ASSET_PATHS = "\"StockApp/Preview Content\""; DEVELOPMENT_TEAM = N94CS4N6VR; ENABLE_PREVIEWS = YES; @@ -2081,9 +2058,10 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockApp; + MARKETING_VERSION = 1.0.2; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; @@ -2095,7 +2073,7 @@ }; 7FE8370628BF95B7003761FE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 952411984CAC3120E22BFF1F /* Pods-StockAppTests.debug.xcconfig */; + baseConfigurationReference = 0A9C39889FC55D51A0332551 /* Pods-StockAppTests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -2106,7 +2084,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockAppTests; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -2120,7 +2098,7 @@ }; 7FE8370728BF95B7003761FE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6CB14FC76BB1C744011FED7C /* Pods-StockAppTests.release.xcconfig */; + baseConfigurationReference = CC7943DDBA7996F5DB766F31 /* Pods-StockAppTests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -2131,7 +2109,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockAppTests; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -2145,7 +2123,7 @@ }; 7FE8370928BF95B7003761FE /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 165FFC9211C79A8DE8904D6E /* Pods-StockApp-StockAppUITests.debug.xcconfig */; + baseConfigurationReference = D8C5D58B49420E55F813AD43 /* Pods-StockApp-StockAppUITests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; @@ -2154,7 +2132,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockAppUITests; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -2168,7 +2146,7 @@ }; 7FE8370A28BF95B7003761FE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7D23965C93E51F805801B6EA /* Pods-StockApp-StockAppUITests.release.xcconfig */; + baseConfigurationReference = 87844FB9D1EFF7706DB196F2 /* Pods-StockApp-StockAppUITests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; @@ -2177,7 +2155,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 15.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = Roy.com.StockAppUITests; + PRODUCT_BUNDLE_IDENTIFIER = Roy.com.CoinMoya; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; diff --git a/StockApp/StockApp.xcodeproj/xcshareddata/xcschemes/StockApp.xcscheme b/StockApp/StockApp.xcodeproj/xcshareddata/xcschemes/StockApp.xcscheme index 7aa9447..c3c1c38 100644 --- a/StockApp/StockApp.xcodeproj/xcshareddata/xcschemes/StockApp.xcscheme +++ b/StockApp/StockApp.xcodeproj/xcshareddata/xcschemes/StockApp.xcscheme @@ -1,6 +1,6 @@ Editor CFBundleURLSchemes - com.googleusercontent.apps.1060378286730-d080s67ukoj1bll1ejs0bu154mbna1j7 + com.googleusercontent.apps.1060378286730-29djldpanil8cgbcgqnrh8dt4b751042 diff --git a/StockApp/StockApp/Model/User/UserModel.swift b/StockApp/StockApp/Model/UserModel/UserModel.swift similarity index 100% rename from StockApp/StockApp/Model/User/UserModel.swift rename to StockApp/StockApp/Model/UserModel/UserModel.swift diff --git a/StockApp/StockApp/StockApp.entitlements b/StockApp/StockApp/StockApp.entitlements index 905d726..a812db5 100644 --- a/StockApp/StockApp/StockApp.entitlements +++ b/StockApp/StockApp/StockApp.entitlements @@ -2,13 +2,9 @@ - aps-environment - development com.apple.developer.applesignin Default - com.apple.developer.in-app-payments - diff --git a/StockApp/StockApp/StockAppDebug.entitlements b/StockApp/StockApp/StockAppDebug.entitlements new file mode 100644 index 0000000..a812db5 --- /dev/null +++ b/StockApp/StockApp/StockAppDebug.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.developer.applesignin + + Default + + + diff --git a/StockApp/StockApp/Utills/ImagePickers/ImagePicker.swift b/StockApp/StockApp/Utills/ImageManager/ImagePicker.swift similarity index 99% rename from StockApp/StockApp/Utills/ImagePickers/ImagePicker.swift rename to StockApp/StockApp/Utills/ImageManager/ImagePicker.swift index 290cb98..9c95d5d 100644 --- a/StockApp/StockApp/Utills/ImagePickers/ImagePicker.swift +++ b/StockApp/StockApp/Utills/ImageManager/ImagePicker.swift @@ -22,7 +22,6 @@ struct ImagePicker: UIViewControllerRepresentable { } func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { - } } diff --git a/StockApp/StockApp/Utills/ImageUploaders/ImageUploader.swift b/StockApp/StockApp/Utills/ImageManager/ImageUploader.swift similarity index 56% rename from StockApp/StockApp/Utills/ImageUploaders/ImageUploader.swift rename to StockApp/StockApp/Utills/ImageManager/ImageUploader.swift index 125dced..d5a8e2d 100644 --- a/StockApp/StockApp/Utills/ImageUploaders/ImageUploader.swift +++ b/StockApp/StockApp/Utills/ImageManager/ImageUploader.swift @@ -5,27 +5,32 @@ // Created by 권승용 on 2022/12/09. // import FirebaseStorage +import Firebase import UIKit struct ImageUploader { - static func uploadImage(image: UIImage, completion: @escaping(String) -> Void) { - guard let imageData = image.jpegData(compressionQuality: 0.5) else { return } + static func uploadImage(image: UIImage, completion: @escaping(URL) -> Void) { + guard let imageData = image.jpegData(compressionQuality: 0.1) else { return } - let fileName = UUID().uuidString - let storageReference = Storage.storage().reference(withPath: "/profile_image/\(fileName)") + guard let fileName = Auth.auth().currentUser?.uid else { + debugPrint("[ERROR] : ImageUploader에서 유저 세션 nil") + return + } + + let storageReference = Storage.storage().reference(withPath: "/profile_images/\(fileName)") storageReference.putData(imageData, metadata: nil) { _, error in if let error = error { - print("DEBUG: 프로필 이미지 업로드 실패 : \(error.localizedDescription)") + print("[ERROR] : 프로필 이미지 업로드 실패 : \(error.localizedDescription)") } storageReference.downloadURL { imageURL, error in if let error = error { - print("DEBUG: URL 다운로드 실패 : \(error.localizedDescription)") + print("[ERROR] : URL 다운로드 실패 : \(error.localizedDescription)") } - guard let imageURL = imageURL?.absoluteString else { return } + guard let imageURL = imageURL else { return } completion(imageURL) } } diff --git a/StockApp/StockApp/View/Components/POPUP/withDrawPOPUPView.swift b/StockApp/StockApp/View/Components/POPUP/withDrawPOPUPView.swift new file mode 100644 index 0000000..20cd500 --- /dev/null +++ b/StockApp/StockApp/View/Components/POPUP/withDrawPOPUPView.swift @@ -0,0 +1,104 @@ +// +// withDrawPOPUPView.swift +// StockApp +// +// Created by 서원지 on 2023/02/07. +// + +import SwiftUI + +struct withDrawPOPUPView: View { + var title: String + var message: String + var cancelTitle: String = "취소" + var confiremTitle: String = "확인" + + @State var closedAlert: Bool = false + var confirmAction: () -> Void = {} + + var body: some View { + VStack(alignment: .center) { + customAlertTitle() + + Spacer() + .frame(height: 22) + + alertConfirmButton() + } + .padding(EdgeInsets(top: 40, leading: 30, bottom: 31, trailing: 30)) + .frame(width: ContentsWidth, height: 200) + .background(Color.colorAssets.navy2) + .cornerRadius(30.0) + .shadow(color: Color.fontColor.accentColor, radius: 6, x: 0, y: .zero) + .animation(.easeOut) + .edgesIgnoringSafeArea(.all) + } + //MARK: - 알림창 타이틀 및 메세지 + @ViewBuilder + private func customAlertTitle() -> some View { + Text(title) + .kerning(-0.36) + .spoqaHan(family: .Bold, size: 18) + .foregroundColor(.white) + .frame(width: ContentsWidth - 60) + + Spacer() + .frame(height: 13) + + Text(message) + .kerning(-0.3) + .spoqaHan(family: .Bold, size: 18) + .foregroundColor(Color.colorAssets.white2) + .fixedSize(horizontal: false, vertical: true) + .multilineTextAlignment(.center) + .frame(width: ContentsWidth-60) + } + + //MARK: - 알림 버튼 취소 확인 버튼 + @ViewBuilder + private func alertConfirmButton() -> some View { + HStack { + Button { + self.closedAlert = false + } label: { + Text(cancelTitle) + .kerning(-0.34) + .spoqaHan(family: .Bold, size: 18) + .foregroundColor(Color.colorAssets.white2) + .frame(width: 140, height: 40) + .overlay( + RoundedRectangle(cornerRadius: 30) + .stroke(Color.white, lineWidth: 1) + .frame(width: 140, height: 40) + ) + } + .frame(width: 140, height: 40) + // .background(Color.colorAssets.white) + .cornerRadius(30.0) + .shadow(color: Color.colorAssets.white.opacity(0.4), radius: 6, x: 0, y: 3) + + Spacer() + .frame(width: 30) + + Button { + confirmAction() + } label: { + Text(confiremTitle) + .kerning(-0.34) + .spoqaHan(family: .Bold, size: 18) + .foregroundColor(Color.colorAssets.subColor) + .frame(width: 140, height: 40) + } + .frame(width: 140, height: 40) + .background(Color.colorAssets.white) + .cornerRadius(30.0) + .shadow(color: Color.colorAssets.white.opacity(0.4), radius: 6, x: 0, y: 3) + } + } +} + +struct withDrawPOPUPView_Previews: PreviewProvider { + static var previews: some View { + withDrawPOPUPView(title: "회원탈퇴", message: "회원탈퇴") {} + } +} diff --git a/StockApp/StockApp/View/Components/TextField/CustomDisabledInputField.swift b/StockApp/StockApp/View/Components/TextField/CustomDisabledInputField.swift new file mode 100644 index 0000000..0c5bdb4 --- /dev/null +++ b/StockApp/StockApp/View/Components/TextField/CustomDisabledInputField.swift @@ -0,0 +1,49 @@ +// +// CustomDisabledInputField.swift +// StockApp +// +// Created by 권승용 on 2022/12/22. +// + +import SwiftUI + +struct CustomDisabledInputField: View { + let imageName: String + let placeHolderText: String + @Binding var text: String + + var body: some View { + VStack { + HStack { + Image(systemName: imageName) + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .foregroundColor(Color(.darkGray)) + + Spacer() + .frame(width: 10) + + TextField(placeHolderText, text: $text) + .spoqaHan(family: .Regular, size: 20) + .disabled(true) + } + .padding() + .background( + RoundedRectangle(cornerRadius: 15) + .stroke(Color(.darkGray), lineWidth: 1) + .shadow(color: .gray.opacity(0.5), radius: 10, x: .zero, y: .zero) + ) + } + .padding(20) + .frame(width: UIScreen.screenWidth ,height: 50) + } +} + +struct CustomDisabledInputField_Previews: PreviewProvider { + static var previews: some View { + CustomInputField(imageName: "flame", + placeHolderText: "Email", + text: .constant("")) + } +} diff --git a/StockApp/StockApp/View/MyProfile/MyProfileEditView.swift b/StockApp/StockApp/View/MyProfile/MyProfileEditView.swift index 68f03cc..bf3a0c9 100644 --- a/StockApp/StockApp/View/MyProfile/MyProfileEditView.swift +++ b/StockApp/StockApp/View/MyProfile/MyProfileEditView.swift @@ -14,6 +14,7 @@ struct MyProfileEditView: View { @EnvironmentObject var authViewModel: AuthorizationVIewModel @State private var name: String = "" + @State private var nickName: String = "" @State private var phoneNumber: String = "" @State private var email: String = "" @@ -26,37 +27,30 @@ struct MyProfileEditView: View { Color.colorAssets.backGroundColor .ignoresSafeArea() - VStack(spacing: 40){ + ScrollView(){ Spacer() .frame(height: 10) imageEditView() + .padding() Divider() + .padding() VStack(spacing: 20) { - nameEditView() + nickNameEditView() phoneNumberEditView() emailView() + Spacer() + saveButton() } .onAppear() { name = accountViewModel.userName ?? "" + nickName = accountViewModel.userNickName ?? "" phoneNumber = accountViewModel.userPhoneNumber ?? "" - email = authViewModel.userSession?.email ?? "" + email = accountViewModel.userEmail ?? "" } - - Spacer(minLength: .zero) - - saveButton() - - Spacer(minLength: .zero) - } - } - .toolbar { - ToolbarItem(placement: .navigationBarTrailing) { - Text("회원정보 수정") - .font(.spoqaHan(family: .Regular, size: 18)) } } } @@ -79,18 +73,31 @@ struct MyProfileEditView: View { .clipShape(Circle()) Image(systemName: "square.and.pencil") .modifier(EditImageModifier()) - } } else { - ZStack { - Image(systemName: "person.crop.circle.fill") - .resizable() - .renderingMode(.original) - .scaledToFill() - .frame(width: 120, height: 120) - .clipShape(Circle()) - Image(systemName: "square.and.pencil") - .modifier(EditImageModifier()) + if accountViewModel.userImage == nil { + ZStack { + Image(systemName: "person.crop.circle.fill") + .resizable() + .renderingMode(.original) + .scaledToFill() + .frame(width: 120, height: 120) + .clipShape(Circle()) + Image(systemName: "square.and.pencil") + .modifier(EditImageModifier()) + } + } else { + ZStack { + Image(uiImage: accountViewModel.userImage!) + .resizable() + .renderingMode(.original) + .scaledToFill() + .clipShape(Circle()) + Image(systemName: "square.and.pencil") + .modifier(EditImageModifier()) + } + .frame(width: 120 , height: 120) + } } } @@ -103,72 +110,31 @@ struct MyProfileEditView: View { @ViewBuilder private func nameEditView() -> some View { - VStack(alignment: .leading) { - Text("이름") - .font(.spoqaHan(family: .Medium, size: 18)) - - VStack { - TextField("이름", text: $name) - .textFieldStyle(.plain) - .autocorrectionDisabled() - .keyboardType(.namePhonePad) - Rectangle() - .frame(height:1) - } - } - .padding(.horizontal) + CustomInputField(imageName: "", placeHolderText: "이름", text: $name) + } + + @ViewBuilder + private func nickNameEditView() -> some View { + CustomInputField(imageName: "", placeHolderText: "닉네임", text: $nickName) } @ViewBuilder private func phoneNumberEditView() -> some View { - VStack(alignment: .leading) { - Text("전화번호") - .font(.spoqaHan(family: .Medium, size: 18)) - - VStack { - TextField("전화번호", text: $phoneNumber) - .textFieldStyle(.plain) - .autocorrectionDisabled() - .keyboardType(.namePhonePad) - Rectangle() - .frame(height:1) - - } - .cornerRadius(4, corners: .allCorners) - - } - .padding(.horizontal) + CustomInputField(imageName: "", placeHolderText: "전화번호", text: $phoneNumber) } @ViewBuilder private func emailView() -> some View { - VStack(alignment: .leading) { - Text("email") - .font(.spoqaHan(family: .Medium, size: 18)) - - VStack { - TextField("이메일", text: $email) - .textFieldStyle(.plain) - .autocorrectionDisabled() - .keyboardType(.namePhonePad) - .disabled(true) - .foregroundColor(Color("Gray")) - Rectangle() - .frame(height:1) - - } - .cornerRadius(4, corners: .allCorners) - - } - .padding(.horizontal) + CustomDisabledInputField(imageName: "", placeHolderText: "이메일", text: $email) } @ViewBuilder private func saveButton() -> some View { Button { - accountViewModel.saveUserInformation(name: name, phoneNumber: phoneNumber) + accountViewModel.saveUserInformation(name: name, nickName: nickName, phoneNumber: phoneNumber) if let selectedImage = selectedImage { - accountViewModel.uploadProfileImage(selectedImage) + accountViewModel.userImage = selectedImage + accountViewModel.saveProfileImage(selectedImage) } } label : { ZStack { @@ -179,11 +145,9 @@ struct MyProfileEditView: View { .foregroundColor(Color("White")) .font(.spoqaHan(family: .Medium, size: 20)) } - } } - // MARK: - 일반함수 func loadImage() { guard let selectedImage = selectedImage else { return } diff --git a/StockApp/StockApp/View/MyProfile/ProfileMainView.swift b/StockApp/StockApp/View/MyProfile/ProfileMainView.swift index 847def3..d020078 100644 --- a/StockApp/StockApp/View/MyProfile/ProfileMainView.swift +++ b/StockApp/StockApp/View/MyProfile/ProfileMainView.swift @@ -7,10 +7,11 @@ import SwiftUI import ExytePopupView +import Firebase struct ProfileMainView: View { - @EnvironmentObject var viewModel: AuthorizationVIewModel + @EnvironmentObject var authViewModel: AuthorizationVIewModel @EnvironmentObject var accountViewModel: AccountManageViewModel @StateObject var profileViewModel = ProfilViewModel() @@ -18,11 +19,12 @@ struct ProfileMainView: View { @State private var developerListButton: Bool = false @State private var personalInformationButton: Bool = false @State private var showAlertLogout: Bool = false + @State private var showAlertWithDrawPOPView: Bool = false @State private var sendEmailButton: Bool = false @State private var noticeButton: Bool = false @State private var profileEditButton: Bool = false - @State private var settingButton: Bool = false - + @State private var settingButton: Bool = false + var body: some View { if #available(iOS 16.0, *) { @@ -36,7 +38,7 @@ struct ProfileMainView: View { VStack(alignment: .leading) { spacingHeight(height: 32) - profileHeader(userName: accountViewModel.userName ?? "Roy", email: accountViewModel.userEmail ?? "shuwj199@gmail.com") + profileHeader() spacingHeight(height: 40) @@ -58,7 +60,7 @@ struct ProfileMainView: View { } .popup(isPresented: $showAlertLogout, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { PopupView() - .environmentObject(viewModel) + .environmentObject(authViewModel) } .popup(isPresented: $noticeButton, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { ReadyPopUPview() @@ -69,9 +71,11 @@ struct ProfileMainView: View { .popup(isPresented: $sendEmailButton, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { ReadyPopUPview() } - } - .onAppear { - accountViewModel.getUserInformation() + .popup(isPresented: $showAlertWithDrawPOPView, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { + withDrawPOPUPView(title: "회원탈퇴", message: "진짜 회원 탈퇴를 하시겠어요 ??") { + authViewModel.withdrawUser() + } + } } } else { NavigationView { @@ -83,7 +87,7 @@ struct ProfileMainView: View { VStack(alignment: .leading) { spacingHeight(height: 32) - profileHeader(userName: accountViewModel.userName ?? "Roy", email: accountViewModel.userEmail ?? "shuwj199@gmail.com") + profileHeader() spacingHeight(height: 40) @@ -104,7 +108,7 @@ struct ProfileMainView: View { } .popup(isPresented: $showAlertLogout, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { PopupView() - .environmentObject(viewModel) + .environmentObject(authViewModel) } .popup(isPresented: $noticeButton, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { ReadyPopUPview() @@ -115,26 +119,42 @@ struct ProfileMainView: View { .popup(isPresented: $sendEmailButton, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { ReadyPopUPview() } + .popup(isPresented: $showAlertWithDrawPOPView, type: .default, position: .bottom, animation: .spring(), closeOnTap: true, closeOnTapOutside: true) { + withDrawPOPUPView(title: "회원탈퇴", message: "진짜 회원 탈퇴를 하시겠어요 ??") { + authViewModel.withdrawUser() + } + } } } } + //MARK: - 프로필 상단 @ViewBuilder - private func profileHeader(userName: String, email: String) -> some View { + private func profileHeader() -> some View { HStack { - Circle() - .frame(width: 60, height: 60) - .overlay { - Image("로이") - } + if accountViewModel.userImage == nil { + Image(systemName: "person.crop.circle.fill") + .resizable() + .renderingMode(.original) + .scaledToFill() + .frame(width: 80, height: 80) + .clipShape(Circle()) + } else { + Image(uiImage: accountViewModel.userImage!) + .resizable() + .renderingMode(.original) + .scaledToFill() + .frame(width: 80, height: 80) + .clipShape(Circle()) + } Spacer() .frame(width: 20) VStack(alignment: .leading , spacing: 5) { - Text(userName) + Text(accountViewModel.userNickName ?? "") .spoqaHan(family: .Bold, size: 18) - Text(email) + Text(Auth.auth().currentUser?.email ?? "") } Spacer() } @@ -142,18 +162,21 @@ struct ProfileMainView: View { .padding(.horizontal, 30) .padding(.bottom , 20) } + //MARK: - 스페이싱 높이 @ViewBuilder private func spacingHeight(height: CGFloat) -> some View { Spacer() .frame(height: height) } + //MARK: - 스페이싱 넓이 @ViewBuilder private func spacingWidth(width: CGFloat) -> some View { Spacer() .frame(width: width) } + //MARK: - 공지 사항 및 환경설정 뷰 @ViewBuilder private func editProfile() -> some View { @@ -162,7 +185,7 @@ struct ProfileMainView: View { ForEach(ProfileEditViewModel.allCases , id: \.rawValue) { item in if item == .notice { Button { - noticeButton.toggle() +// noticeButton.toggle() } label: { ProfileEditView(image: item.imageName, title: item.description) // .background( @@ -186,7 +209,7 @@ struct ProfileMainView: View { } else if item == .appSetting { Button { - settingButton.toggle() +// settingButton.toggle() } label: { ProfileEditView(image: item.imageName, title: item.description) // .background( @@ -201,6 +224,7 @@ struct ProfileMainView: View { } spacingHeight(height: 30) } + //MARK: - 앱 정보 @ViewBuilder private func appInformationListButton() -> some View { @@ -246,6 +270,7 @@ struct ProfileMainView: View { .padding(.horizontal) spacingHeight(height: 30) } + //MARK: - 피드백 @ViewBuilder private func feedBackListButton() -> some View { @@ -277,6 +302,7 @@ struct ProfileMainView: View { .padding(.horizontal) spacingHeight(height: 30) } + //MARK: - 앱 계정 관리 @ViewBuilder private func logoutListButton() -> some View { @@ -288,6 +314,13 @@ struct ProfileMainView: View { } label: { ListRowSystemImageTextView(title: item.description, imageName: item.imageName, width: 15, height: 20) } + } else if item == .withDraw { + Button { + showAlertWithDrawPOPView = true + } label: { + ListRowSystemImageTextView(title: item.description, imageName: item.imageName, width: 15, height: 20) + } + } } }header: { @@ -298,6 +331,7 @@ struct ProfileMainView: View { .padding(.horizontal) spacingHeight(height: 30) } + //MARK: - 앱 정보 및 기타 @ViewBuilder private func appinformationEtcButton() -> some View { @@ -313,7 +347,7 @@ struct ProfileMainView: View { .foregroundColor(Color.fontColor.mainFontColor) } .padding(.horizontal) - spacingHeight(height: 30) + spacingHeight(height: 100) } } diff --git a/StockApp/StockApp/View/MyProfile/UserModel.swift b/StockApp/StockApp/View/MyProfile/UserModel.swift new file mode 100644 index 0000000..74c5f1c --- /dev/null +++ b/StockApp/StockApp/View/MyProfile/UserModel.swift @@ -0,0 +1,16 @@ +// +// UserModel.swift +// StockApp +// +// Created by 서원지 on 2022/12/16. +// + +import FirebaseFirestoreSwift + +struct UserModel: Identifiable, Decodable{ + @DocumentID var id: String? + let username: String + let fullname: String + let phonenumber: String + let email: String +} diff --git a/StockApp/StockApp/View/SignUp/SIgnUpVIew.swift b/StockApp/StockApp/View/SignUp/SIgnUpVIew.swift index a735f0d..4946653 100644 --- a/StockApp/StockApp/View/SignUp/SIgnUpVIew.swift +++ b/StockApp/StockApp/View/SignUp/SIgnUpVIew.swift @@ -134,7 +134,7 @@ struct SIgnUpVIew: View { private func signUPButton() -> some View { Button { checkRegisterTextField() - viewModel.register(withEmail: email, password: password, fullname: nickName, phoneNumber: phoneNumber, userName: userName) + viewModel.register(withEmail: email, password: password, nickName: nickName, phoneNumber: phoneNumber, userName: userName) UIApplication.shared.endEditing() diff --git a/StockApp/StockApp/ViewModel/AccountManageViewModel./AccountManageViewModel.swift b/StockApp/StockApp/ViewModel/AccountManageViewModel./AccountManageViewModel.swift index 2551c28..3061279 100644 --- a/StockApp/StockApp/ViewModel/AccountManageViewModel./AccountManageViewModel.swift +++ b/StockApp/StockApp/ViewModel/AccountManageViewModel./AccountManageViewModel.swift @@ -6,9 +6,14 @@ import FirebaseStorage class AccountManageViewModel: ObservableObject { + static let cache = NSCache() + @Published var userName: String? + @Published var userNickName: String? @Published var userEmail: String? @Published var userPhoneNumber: String? + @Published var userImageURL: URL? + @Published var userImage: UIImage? init() { getUserInformation() @@ -30,40 +35,141 @@ class AccountManageViewModel: ObservableObject { for document in snap!.documentChanges { self.userName = document.document.get("username") as? String + self.userNickName = document.document.get("nickname") as? String self.userEmail = document.document.get("email") as? String self.userPhoneNumber = document.document.get("phonenumber") as? String } } - print("유저 이름: \(self.userName)") + + self.userImageURL = Auth.auth().currentUser?.photoURL + + print("[DEBUG] 유저 이미지 URL : \(String(describing: userImageURL))") + + if userImageURL != nil { + self.getProfileImage() + } + + print("[DEBUG] 유저 이름: \(String(describing: self.userName))") } - func saveUserInformation(name: String, phoneNumber: String) { + func saveUserInformation(name: String, nickName: String, phoneNumber: String) { let collectionPath = Firestore.firestore().collection("users") let userID = Auth.auth().currentUser?.uid - let currentUser = Auth.auth() - collectionPath.document("\(userID!)").updateData(["username": name, "phonenumber": phoneNumber]) { error in + collectionPath.document("\(userID!)").updateData(["username": name, "nickname": nickName, "phonenumber": phoneNumber]) { error in if error != nil { print("[❌] ERROR : 유저 정보 저장 실패") print((error?.localizedDescription)!) return } } + + let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest() + + changeRequest?.displayName = nickName + changeRequest?.commitChanges(){ error in + if let error = error { + print("[ERROR] : photoURL 변경 중 에러 발생 \(error.localizedDescription)") + } + else { + print("[DEBUG] : dispalyName 변경 성공") + + } + } + + Auth.auth().currentUser?.reload() } - // UIImage 사용 이유 : UIImage만이 imageData로 변환 가능함 - func uploadProfileImage(_ image: UIImage) { - guard let uid = Auth.auth().currentUser?.uid else { return } - + func saveProfileImage(_ image: UIImage) { ImageUploader.uploadImage(image: image) { profileImageURL in - Firestore.firestore().collection("users") - .document(uid) - .updateData(["profileImageURL": profileImageURL]) { error in - if error != nil { - print("[❌] ERROR : 유저 프로필 이미지 업로드 실패") - } + + let dataTask = URLSession.shared.dataTask(with: profileImageURL) { data, responseURL, error in + print("[DEBUG] : data 출력 : \(String(describing: data))") + + if error != nil { + print("[ERROR] : 이미지 다운로드 실패 \(String(describing: error?.localizedDescription))") + } + + var downloadedImage: UIImage? + + if let data = data { + print("[DEBUG] : 데이터 언랩 후 UIImage 형태로 저장 성공") + downloadedImage = UIImage(data: data) } + + if downloadedImage != nil { + print("[DEBUG] : 이미지 캐시에 저장 완료") + AccountManageViewModel.cache.setObject(downloadedImage!, forKey: profileImageURL.absoluteString as NSString) + } + + DispatchQueue.main.async { + print("[DEBUG] : 유저 이미지 저장") + self.userImage = downloadedImage + } + print("[DEBUG] : 유저 이미지 : \(String(describing: self.userImage))") + } + dataTask.resume() + + let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest() + + changeRequest?.photoURL = profileImageURL + changeRequest?.commitChanges(){ error in + if let error = error { + print("[ERROR] : photoURL 변경 중 에러 발생 \(error.localizedDescription)") + } + else { + print("[DEBUG] : photoURL 업로드 성공") + } + } + } + } + + func downloadProfileImage() { + print("[DEBUG] : downloadImaeg 실행") + + if let url = userImageURL { + print("[DEBUG] : 이미지 url 옵셔널 언래핑 성공") + let dataTask = URLSession.shared.dataTask(with: url) { data, responseURL, error in + print("[DEBUG] : data 출력 : \(String(describing: data))") + + if error != nil { + print("[ERROR] : 이미지 다운로드 실패 \(String(describing: error?.localizedDescription))") + } + + var downloadedImage: UIImage? + + if let data = data { + print("[DEBUG] : 데이터 언랩 후 UIImage 형태로 저장 성공") + downloadedImage = UIImage(data: data) + } + + if downloadedImage != nil { + print("[DEBUG] : 이미지 캐시에 저장 완료") + AccountManageViewModel.cache.setObject(downloadedImage!, forKey: url.absoluteString as NSString) + } + + DispatchQueue.main.async { + print("[DEBUG] : 유저 이미지 저장") + self.userImage = downloadedImage + } + print("[DEBUG] : 유저 이미지 : \(String(describing: self.userImage))") + } + + dataTask.resume() + } else { + print("[ERROR] : 이미지 uRL = nil, \(String(describing: userImageURL))") } + } + + func getProfileImage() { + print("[DEBUG] : getProfileImage 실행") + if let cacheImage = AccountManageViewModel.cache.object(forKey: self.userImageURL!.absoluteString as NSString) { + self.userImage = cacheImage + } else { + Task { + downloadProfileImage() + } + } } } diff --git a/StockApp/StockApp/ViewModel/AuthorizationViewModel/AuthorizationVIewModel.swift b/StockApp/StockApp/ViewModel/AuthorizationViewModel/AuthorizationVIewModel.swift index 47ffdc6..6989e56 100644 --- a/StockApp/StockApp/ViewModel/AuthorizationViewModel/AuthorizationVIewModel.swift +++ b/StockApp/StockApp/ViewModel/AuthorizationViewModel/AuthorizationVIewModel.swift @@ -16,13 +16,12 @@ class AuthorizationVIewModel: ObservableObject { //MARK: - 유저 @Published var userSession: FirebaseAuth.User? @Published var nonce = "" - @StateObject var accountViewModel = AccountManageViewModel() + @AppStorage("log_status") var log_Status = false init() { self.userSession = Auth.auth().currentUser - debugPrint("DEBUG: User session is \(self.userSession)") - + debugPrint("DEBUG: User session is \(String(describing: self.userSession))") } //MARK: - 로그인 @@ -35,14 +34,13 @@ class AuthorizationVIewModel: ObservableObject { } else { guard let user = result?.user else { return } self.userSession = user - self.accountViewModel.getUserInformation() debugPrint("로그인에 성공 하였습니다") } } } //MARK: - 회원 가입 - func register(withEmail email: String, password: String, fullname: String, phoneNumber: String, userName: String) { + func register(withEmail email: String, password: String, nickName: String, phoneNumber: String, userName: String) { Auth.auth().createUser(withEmail: email, password: password) { result, error in if let error = error { debugPrint("[🔥] 회원가입에 실패 하였습니다 \(error.localizedDescription)") @@ -52,18 +50,32 @@ class AuthorizationVIewModel: ObservableObject { guard let user = result?.user else { return } self.userSession = user debugPrint("회원가입에 성공 하였습니다 ") - debugPrint("debug user is \(self.userSession)") + debugPrint("debug user is \(String(describing: self.userSession))") let data = ["email" : email , "username" : userName.lowercased(), - "fullname" : fullname, + "nickname" : nickName, "phonenumber" : phoneNumber, "uid" : user.uid] + Firestore.firestore().collection("users") .document(user.uid) .setData(data) { data in - debugPrint("DEBUG : Upload user data : \(data)") + debugPrint("DEBUG : Upload user data : \(String(describing: data))") + } + + let changeRequest = user.createProfileChangeRequest() + + changeRequest.displayName = nickName + changeRequest.commitChanges(){ error in + if let error = error { + print("[ERROR] : displayName 변경 중 에러 발생 \(error.localizedDescription)") + } + else { + print("[DEBUG] : dispalyName 변경 성공") + self.userSession = user } + } } } @@ -100,6 +112,7 @@ class AuthorizationVIewModel: ObservableObject { } } } + //MARK: - 구글 로그인 func googleLogin() { guard let clientID = FirebaseApp.app()?.options.clientID else { return } @@ -116,7 +129,7 @@ class AuthorizationVIewModel: ObservableObject { let idToken = authentication.idToken else { - debugPrint("[🔥] 로그인에 성공 하였습니다 \(user?.profile?.email)") + debugPrint("[🔥] 로그인에 성공 하였습니다 \(String(describing: user?.profile?.email))") // self.userSession = user return } @@ -129,14 +142,12 @@ class AuthorizationVIewModel: ObservableObject { debugPrint("[🔥] 로그인 에 실패 하였습니다 \(error.localizedDescription)") return } else { - debugPrint("[🔥] 로그인에 성공 하였습니다 \(user)") + debugPrint("[🔥] 로그인에 성공 하였습니다 \(String(describing: user))") guard let user = authResult?.user else {return} self.userSession = user } } - } - } //MARK: - 로그아웃 @@ -151,4 +162,24 @@ class AuthorizationVIewModel: ObservableObject { print("Error signing out: %@", signOutError) } } + + func withdrawUser() { + let firebaseAuth = Auth.auth() + + firebaseAuth.currentUser?.delete(completion: { error in + print("유저가 삭제 되었습니다 \(String(describing: error?.localizedDescription))") + }) + + let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest() + changeRequest?.commitChanges() { error in + if let error = error { + print("[ERROR] : photoURL 변경 중 에러 발생 \(error.localizedDescription)") + } + else { + print("[DEBUG] : dispalyName 변경 성공") + self.log_Status = false + } + } + Auth.auth().currentUser?.reload() + } } diff --git a/StockApp/StockApp/ViewModel/SettingViewModel/AppLogoutViewModel.swift b/StockApp/StockApp/ViewModel/SettingViewModel/AppLogoutViewModel.swift index 4a10c19..b8c2e87 100644 --- a/StockApp/StockApp/ViewModel/SettingViewModel/AppLogoutViewModel.swift +++ b/StockApp/StockApp/ViewModel/SettingViewModel/AppLogoutViewModel.swift @@ -9,11 +9,14 @@ import Foundation enum AppLogoutViewModel: Int, CaseIterable, CustomStringConvertible { case logout + case withDraw var description: String { switch self { case .logout: return "로그아웃 " + case .withDraw: + return "회원탈퇴" } } @@ -21,6 +24,8 @@ enum AppLogoutViewModel: Int, CaseIterable, CustomStringConvertible { switch self { case .logout: return "rectangle.portrait.and.arrow.forward" + case .withDraw: + return "rectangle.portrait.and.arrow.forward" } }