From f1e2debf4c13861c9dc62dfad3145049e56ae832 Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sat, 22 Jun 2024 09:32:12 +0900 Subject: [PATCH 01/31] implemented gbnetwork --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 71 +++++++++++++------ .../Network/InfrastructureDummy.swift | 17 ----- 2 files changed, 51 insertions(+), 37 deletions(-) delete mode 100644 GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index b3204027..be57cbe0 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -227,7 +227,6 @@ 3EF9F8B22BBD119200F3E366 /* DummyEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8B12BBD119200F3E366 /* DummyEntity.swift */; }; 3EF9F8B42BBD119A00F3E366 /* DummyError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8B32BBD119A00F3E366 /* DummyError.swift */; }; 3EF9F8B72BBD141600F3E366 /* DummyEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8B62BBD141600F3E366 /* DummyEndpoint.swift */; }; - 3EF9F8BB2BBD228C00F3E366 /* InfrastructureDummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */; }; 3EFA97862A5EBCA9002E70FA /* LineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFA97852A5EBCA9002E70FA /* LineView.swift */; }; 3EFA97882A5EBCED002E70FA /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFA97872A5EBCED002E70FA /* CustomNavigationBar.swift */; }; DF483ACC2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF483ACB2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift */; }; @@ -262,6 +261,23 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3E3DE9F32C25D28200CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E35BFD22C1195AD007D399C; + remoteInfo = GBNetwork; + }; + 3E3DE9F52C25D28200CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E35BFDC2C1195AD007D399C; + remoteInfo = GBNetworkTests; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 0905561F2A51DB2C00752067 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 090556212A51DB3300752067 /* UIFont+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+.swift"; sourceTree = ""; }; @@ -388,6 +404,7 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; + 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = "../../../gbnetwork-framework/GBNetwork/GBNetwork.xcodeproj"; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -477,7 +494,6 @@ 3EF9F8B12BBD119200F3E366 /* DummyEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyEntity.swift; sourceTree = ""; }; 3EF9F8B32BBD119A00F3E366 /* DummyError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyError.swift; sourceTree = ""; }; 3EF9F8B62BBD141600F3E366 /* DummyEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyEndpoint.swift; sourceTree = ""; }; - 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructureDummy.swift; sourceTree = ""; }; 3EFA97852A5EBCA9002E70FA /* LineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineView.swift; sourceTree = ""; }; 3EFA97872A5EBCED002E70FA /* CustomNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; DF483ACB2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkReviewNumberStackView.swift; sourceTree = ""; }; @@ -943,7 +959,6 @@ 3EF9F89A2BBD109E00F3E366 /* Domain */, 3EF9F89B2BBD10A000F3E366 /* Data */, 3E8C47CE2BC385A800919E06 /* Core */, - 3E1A4EDD2BCD2343004CA603 /* Infrastructure */, 0961C36B2A501F050031A822 /* Resource */, 0961C3602A501E9F0031A822 /* Global */, ); @@ -1112,14 +1127,6 @@ path = Scene; sourceTree = ""; }; - 3E1A4EDD2BCD2343004CA603 /* Infrastructure */ = { - isa = PBXGroup; - children = ( - 3EF9F8B82BBD17F400F3E366 /* Network */, - ); - path = Infrastructure; - sourceTree = ""; - }; 3E1E73FF2B78AD460082386A /* Model */ = { isa = PBXGroup; children = ( @@ -1163,6 +1170,15 @@ path = NavigationBar; sourceTree = ""; }; + 3E3DE9EF2C25D28200CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */, + 3E3DE9F62C25D28200CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1239,6 +1255,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( + 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1764,14 +1781,6 @@ path = Network; sourceTree = ""; }; - 3EF9F8B82BBD17F400F3E366 /* Network */ = { - isa = PBXGroup; - children = ( - 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */, - ); - path = Network; - sourceTree = ""; - }; DF697C082A686ABC008CE4CF /* Cell */ = { isa = PBXGroup; children = ( @@ -1940,6 +1949,12 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3E3DE9EF2C25D28200CA5999 /* Products */; + ProjectRef = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -1947,6 +1962,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = GBNetwork.framework; + remoteRef = 3E3DE9F32C25D28200CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3E3DE9F62C25D28200CA5999 /* GBNetworkTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GBNetworkTests.xctest; + remoteRef = 3E3DE9F52C25D28200CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -2176,7 +2208,6 @@ 3EB798182AB7D42B004EC35D /* DeleteUserResponseDTO.swift in Sources */, 0905562B2A51DBCE00752067 /* UIStackView+.swift in Sources */, 3E8C47F52BC3C9FC00919E06 /* BakeryListCoordinator.swift in Sources */, - 3EF9F8BB2BBD228C00F3E366 /* InfrastructureDummy.swift in Sources */, 09B13F562A59410C00C0C723 /* CALayer+.swift in Sources */, 09CD07902A620D7D00A078DE /* NickNameViewController.swift in Sources */, DFB1343D2A6284BB00BAB52E /* ReviewProgressView.swift in Sources */, diff --git a/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift b/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift deleted file mode 100644 index 33f4c75d..00000000 --- a/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Endpoint.swift -// GEON-PPANG-iOS -// -// Created by 이성민 on 4/3/24. -// - -import Foundation - -/// `Domain 레이어를 모르면서` Data 레이어에서 신경쓰지 않아도 될 요소들 구현 -/// -/// e.g. -/// - APIClient: API 통신하는 실질적인 부분, request 등과 같은 것들 구현하면 좋을듯 -/// - 외부 DB랑 내부 DB랑 따로 구분해야 할수도 -/// - APIConfiguration도 여기서 정의해두는게 좋을듯, header 등 -/// - Endpoint: 실질적인 `요청을 보내는` 형태 -/// - 그 외에도 현재 `Global/Network/Base`에 있는 몇가지 요소들 등 여기에 구현 From ac17ada8f7985d728301048da1d04391c66385b8 Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sat, 22 Jun 2024 14:27:02 +0900 Subject: [PATCH 02/31] [Chore] #276 - applied gbnetwork framework --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index be57cbe0..2c1cd794 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,6 +138,8 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; + 3E3DE9FE2C26981200CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */; }; + 3E3DE9FF2C26981200CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -278,6 +280,20 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3E3DE9FF2C26981200CA5999 /* GBNetwork.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 0905561F2A51DB2C00752067 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 090556212A51DB3300752067 /* UIFont+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+.swift"; sourceTree = ""; }; @@ -539,6 +555,7 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, + 3E3DE9FE2C26981200CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -940,6 +957,7 @@ 09E30E812BFEF16F001E107B /* ci_scripts */, 098F32DF2A4200FD0092D09A /* GEON-PPANG-iOS */, 098F32DE2A4200FD0092D09A /* Products */, + 3E3DE9FD2C26981200CA5999 /* Frameworks */, ); sourceTree = ""; }; @@ -1179,6 +1197,13 @@ name = Products; sourceTree = ""; }; + 3E3DE9FD2C26981200CA5999 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1893,6 +1918,7 @@ 098F32DA2A4200FD0092D09A /* Frameworks */, 098F32DB2A4200FD0092D09A /* Resources */, 099FC1C92A51F23B00116D00 /* Sentry */, + 3E3DEA002C26981200CA5999 /* Embed Frameworks */, ); buildRules = ( ); From 252d07b037a51d64920c3fa49e92de6e871a9455 Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 23 Jun 2024 00:26:22 +0900 Subject: [PATCH 03/31] [Chore] #276 - editing details --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 42 +++++++++---------- .../xcshareddata/swiftpm/Package.resolved | 3 +- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 2c1cd794..30330be1 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,8 +138,7 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; - 3E3DE9FE2C26981200CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */; }; - 3E3DE9FF2C26981200CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3E3DEA5C2C27247400CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -264,16 +263,16 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 3E3DE9F32C25D28200CA5999 /* PBXContainerItemProxy */ = { + 3E3DEA582C27246C00CA5999 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + containerPortal = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3E35BFD22C1195AD007D399C; remoteInfo = GBNetwork; }; - 3E3DE9F52C25D28200CA5999 /* PBXContainerItemProxy */ = { + 3E3DEA5A2C27246C00CA5999 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + containerPortal = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; proxyType = 2; remoteGlobalIDString = 3E35BFDC2C1195AD007D399C; remoteInfo = GBNetworkTests; @@ -287,7 +286,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3E3DE9FF2C26981200CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -420,7 +418,7 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; - 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = "../../../gbnetwork-framework/GBNetwork/GBNetwork.xcodeproj"; sourceTree = ""; }; + 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = "../../../gbnetwork-framework/GBNetwork/GBNetwork.xcodeproj"; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -549,13 +547,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 3E3DEA5C2C27247400CA5999 /* GBNetwork.framework in Frameworks */, 3E36D7CF2A8DE65D00B2C1CC /* KakaoSDKCommon in Frameworks */, 3E36D7CD2A8DE65D00B2C1CC /* KakaoSDKAuth in Frameworks */, 0959F19A2A65D45700E77CAF /* Kingfisher in Frameworks */, 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, - 3E3DE9FE2C26981200CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1188,20 +1186,20 @@ path = NavigationBar; sourceTree = ""; }; - 3E3DE9EF2C25D28200CA5999 /* Products */ = { + 3E3DE9FD2C26981200CA5999 /* Frameworks */ = { isa = PBXGroup; children = ( - 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */, - 3E3DE9F62C25D28200CA5999 /* GBNetworkTests.xctest */, ); - name = Products; + name = Frameworks; sourceTree = ""; }; - 3E3DE9FD2C26981200CA5999 /* Frameworks */ = { + 3E3DEA542C27246C00CA5999 /* Products */ = { isa = PBXGroup; children = ( + 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */, + 3E3DEA5B2C27246C00CA5999 /* GBNetworkTests.xctest */, ); - name = Frameworks; + name = Products; sourceTree = ""; }; 3E61EE8F2AA9530D004F25DB /* Review */ = { @@ -1280,7 +1278,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( - 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */, + 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1977,8 +1975,8 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = 3E3DE9EF2C25D28200CA5999 /* Products */; - ProjectRef = 3E3DE9EE2C25D28200CA5999 /* GBNetwork.xcodeproj */; + ProductGroup = 3E3DEA542C27246C00CA5999 /* Products */; + ProjectRef = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; }, ); projectRoot = ""; @@ -1989,18 +1987,18 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 3E3DE9F42C25D28200CA5999 /* GBNetwork.framework */ = { + 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = GBNetwork.framework; - remoteRef = 3E3DE9F32C25D28200CA5999 /* PBXContainerItemProxy */; + remoteRef = 3E3DEA582C27246C00CA5999 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3E3DE9F62C25D28200CA5999 /* GBNetworkTests.xctest */ = { + 3E3DEA5B2C27246C00CA5999 /* GBNetworkTests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = GBNetworkTests.xctest; - remoteRef = 3E3DE9F52C25D28200CA5999 /* PBXContainerItemProxy */; + remoteRef = 3E3DEA5A2C27246C00CA5999 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ diff --git a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5f8ee99d..1b2650ff 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,4 +1,5 @@ { + "originHash" : "a32b0a1c0ad6f6a91a39529043231e700bfb3a573e73a0172a5e40c9106b8bba", "pins" : [ { "identity" : "alamofire", @@ -100,5 +101,5 @@ } } ], - "version" : 2 + "version" : 3 } From edf8b8706c19d16f87b24b8f5578245007d21c6d Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 30 Jun 2024 10:54:55 +0900 Subject: [PATCH 04/31] [Add] #276 - implemented renewed gbnetwork framework --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 40 +++++++++++++----------- GEON-PPANG-iOS/Core/GBNetwork | 1 + 2 files changed, 22 insertions(+), 19 deletions(-) create mode 160000 GEON-PPANG-iOS/Core/GBNetwork diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 30330be1..c867984a 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,7 +138,8 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; - 3E3DEA5C2C27247400CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */; }; + 3E3DEB192C30F25300CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */; }; + 3E3DEB1A2C30F25300CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -263,18 +264,18 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 3E3DEA582C27246C00CA5999 /* PBXContainerItemProxy */ = { + 3E3DEB022C30F1E100CA5999 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; + containerPortal = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 3E35BFD22C1195AD007D399C; + remoteGlobalIDString = 3E3DEAE32C30F1D000CA5999; remoteInfo = GBNetwork; }; - 3E3DEA5A2C27246C00CA5999 /* PBXContainerItemProxy */ = { + 3E3DEB042C30F1E100CA5999 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; + containerPortal = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 3E35BFDC2C1195AD007D399C; + remoteGlobalIDString = 3E3DEAED2C30F1D000CA5999; remoteInfo = GBNetworkTests; }; /* End PBXContainerItemProxy section */ @@ -286,6 +287,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 3E3DEB1A2C30F25300CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -418,7 +420,7 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; - 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = "../../../gbnetwork-framework/GBNetwork/GBNetwork.xcodeproj"; sourceTree = ""; }; + 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -547,13 +549,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3E3DEA5C2C27247400CA5999 /* GBNetwork.framework in Frameworks */, 3E36D7CF2A8DE65D00B2C1CC /* KakaoSDKCommon in Frameworks */, 3E36D7CD2A8DE65D00B2C1CC /* KakaoSDKAuth in Frameworks */, 0959F19A2A65D45700E77CAF /* Kingfisher in Frameworks */, 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, + 3E3DEB192C30F25300CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1193,11 +1195,11 @@ name = Frameworks; sourceTree = ""; }; - 3E3DEA542C27246C00CA5999 /* Products */ = { + 3E3DEAFE2C30F1E100CA5999 /* Products */ = { isa = PBXGroup; children = ( - 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */, - 3E3DEA5B2C27246C00CA5999 /* GBNetworkTests.xctest */, + 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */, + 3E3DEB052C30F1E100CA5999 /* GBNetworkTests.xctest */, ); name = Products; sourceTree = ""; @@ -1278,7 +1280,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( - 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */, + 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1975,8 +1977,8 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = 3E3DEA542C27246C00CA5999 /* Products */; - ProjectRef = 3E3DEA532C27246C00CA5999 /* GBNetwork.xcodeproj */; + ProductGroup = 3E3DEAFE2C30F1E100CA5999 /* Products */; + ProjectRef = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; }, ); projectRoot = ""; @@ -1987,18 +1989,18 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 3E3DEA592C27246C00CA5999 /* GBNetwork.framework */ = { + 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = GBNetwork.framework; - remoteRef = 3E3DEA582C27246C00CA5999 /* PBXContainerItemProxy */; + remoteRef = 3E3DEB022C30F1E100CA5999 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3E3DEA5B2C27246C00CA5999 /* GBNetworkTests.xctest */ = { + 3E3DEB052C30F1E100CA5999 /* GBNetworkTests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = GBNetworkTests.xctest; - remoteRef = 3E3DEA5A2C27246C00CA5999 /* PBXContainerItemProxy */; + remoteRef = 3E3DEB042C30F1E100CA5999 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ diff --git a/GEON-PPANG-iOS/Core/GBNetwork b/GEON-PPANG-iOS/Core/GBNetwork new file mode 160000 index 00000000..0ab05d69 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork @@ -0,0 +1 @@ +Subproject commit 0ab05d69105b226d75eea2fa5b929c1dbd032422 From 1b5fa0df8132ca3dee102b8e93ebe2b58e7a1f0c Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 30 Jun 2024 11:35:16 +0900 Subject: [PATCH 05/31] [Chore] #276 - removed gbnetwork due to error --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 55 ------------------------ 1 file changed, 55 deletions(-) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index c867984a..22a124f1 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,8 +138,6 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; - 3E3DEB192C30F25300CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */; }; - 3E3DEB1A2C30F25300CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -263,23 +261,6 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 3E3DEB022C30F1E100CA5999 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3E3DEAE32C30F1D000CA5999; - remoteInfo = GBNetwork; - }; - 3E3DEB042C30F1E100CA5999 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3E3DEAED2C30F1D000CA5999; - remoteInfo = GBNetworkTests; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -287,7 +268,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3E3DEB1A2C30F25300CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -420,7 +400,6 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; - 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -555,7 +534,6 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, - 3E3DEB192C30F25300CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1195,15 +1173,6 @@ name = Frameworks; sourceTree = ""; }; - 3E3DEAFE2C30F1E100CA5999 /* Products */ = { - isa = PBXGroup; - children = ( - 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */, - 3E3DEB052C30F1E100CA5999 /* GBNetworkTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1280,7 +1249,6 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( - 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1975,12 +1943,6 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 3E3DEAFE2C30F1E100CA5999 /* Products */; - ProjectRef = 3E3DEAFD2C30F1E100CA5999 /* GBNetwork.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -1988,23 +1950,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 3E3DEB032C30F1E100CA5999 /* GBNetwork.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = GBNetwork.framework; - remoteRef = 3E3DEB022C30F1E100CA5999 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3E3DEB052C30F1E100CA5999 /* GBNetworkTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = GBNetworkTests.xctest; - remoteRef = 3E3DEB042C30F1E100CA5999 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; From 3eee810a4550e7dad84e41a8ba224f76f4d74530 Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 30 Jun 2024 13:38:37 +0900 Subject: [PATCH 06/31] [Fix] #276 - remade gbnetwork framework --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 57 +++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 22a124f1..775e964b 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,6 +138,8 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; + 3E3DEB682C31184800CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */; }; + 3E3DEB692C31184800CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -261,6 +263,23 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3E3DEB642C31182C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB332C3117A300CA5999; + remoteInfo = GBNetwork; + }; + 3E3DEB662C31182C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB3D2C3117A400CA5999; + remoteInfo = GBNetworkTests; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -268,6 +287,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 3E3DEB692C31184800CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -400,6 +420,7 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; + 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -534,6 +555,7 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, + 3E3DEB682C31184800CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1173,6 +1195,15 @@ name = Frameworks; sourceTree = ""; }; + 3E3DEB602C31182C00CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */, + 3E3DEB672C31182C00CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1249,6 +1280,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( + 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1882,11 +1914,11 @@ isa = PBXNativeTarget; buildConfigurationList = 098F32F12A4200FE0092D09A /* Build configuration list for PBXNativeTarget "GEON-PPANG-iOS" */; buildPhases = ( + 3E3DEA002C26981200CA5999 /* Embed Frameworks */, 098F32D92A4200FD0092D09A /* Sources */, 098F32DA2A4200FD0092D09A /* Frameworks */, 098F32DB2A4200FD0092D09A /* Resources */, 099FC1C92A51F23B00116D00 /* Sentry */, - 3E3DEA002C26981200CA5999 /* Embed Frameworks */, ); buildRules = ( ); @@ -1943,6 +1975,12 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3E3DEB602C31182C00CA5999 /* Products */; + ProjectRef = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -1950,6 +1988,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = GBNetwork.framework; + remoteRef = 3E3DEB642C31182C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3E3DEB672C31182C00CA5999 /* GBNetworkTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GBNetworkTests.xctest; + remoteRef = 3E3DEB662C31182C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; From 88a0121aea9e5ee0ed50491f1b19a9deb39ce0f8 Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 30 Jun 2024 18:41:32 +0900 Subject: [PATCH 07/31] [Chore] #276 - removed gbnetwork --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 55 --------- .../xcshareddata/swiftpm/Package.resolved | 105 ------------------ GEON-PPANG-iOS/Core/GBNetwork | 1 - 3 files changed, 161 deletions(-) delete mode 100644 GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 160000 GEON-PPANG-iOS/Core/GBNetwork diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 775e964b..0e1b8a6a 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,8 +138,6 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; - 3E3DEB682C31184800CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */; }; - 3E3DEB692C31184800CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -263,23 +261,6 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 3E3DEB642C31182C00CA5999 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3E3DEB332C3117A300CA5999; - remoteInfo = GBNetwork; - }; - 3E3DEB662C31182C00CA5999 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3E3DEB3D2C3117A400CA5999; - remoteInfo = GBNetworkTests; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -287,7 +268,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3E3DEB692C31184800CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -420,7 +400,6 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; - 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -555,7 +534,6 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, - 3E3DEB682C31184800CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1195,15 +1173,6 @@ name = Frameworks; sourceTree = ""; }; - 3E3DEB602C31182C00CA5999 /* Products */ = { - isa = PBXGroup; - children = ( - 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */, - 3E3DEB672C31182C00CA5999 /* GBNetworkTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1280,7 +1249,6 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( - 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1975,12 +1943,6 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 3E3DEB602C31182C00CA5999 /* Products */; - ProjectRef = 3E3DEB5F2C31182C00CA5999 /* GBNetwork.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -1988,23 +1950,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 3E3DEB652C31182C00CA5999 /* GBNetwork.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = GBNetwork.framework; - remoteRef = 3E3DEB642C31182C00CA5999 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3E3DEB672C31182C00CA5999 /* GBNetworkTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = GBNetworkTests.xctest; - remoteRef = 3E3DEB662C31182C00CA5999 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; diff --git a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 1b2650ff..00000000 --- a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,105 +0,0 @@ -{ - "originHash" : "a32b0a1c0ad6f6a91a39529043231e700bfb3a573e73a0172a5e40c9106b8bba", - "pins" : [ - { - "identity" : "alamofire", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Alamofire/Alamofire.git", - "state" : { - "revision" : "3dc6a42c7727c49bf26508e29b0a0b35f9c7e1ad", - "version" : "5.8.1" - } - }, - { - "identity" : "amplitude-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/amplitude/Amplitude-iOS", - "state" : { - "branch" : "main", - "revision" : "82fc62448292c13fa0a6b0b11c4524df83fd3f3b" - } - }, - { - "identity" : "analytics-connector-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/amplitude/analytics-connector-ios.git", - "state" : { - "revision" : "e2ca17ac735bcbc48b13062484541702ef45153d", - "version" : "1.0.3" - } - }, - { - "identity" : "kakao-ios-sdk", - "kind" : "remoteSourceControl", - "location" : "https://github.com/kakao/kakao-ios-sdk", - "state" : { - "revision" : "ae3c60cbd4e3b348775f8c766e5b908fa1e66c5a", - "version" : "2.20.0" - } - }, - { - "identity" : "kingfisher", - "kind" : "remoteSourceControl", - "location" : "https://github.com/onevcat/Kingfisher.git", - "state" : { - "revision" : "5b92f029fab2cce44386d28588098b5be0824ef5", - "version" : "7.11.0" - } - }, - { - "identity" : "moya", - "kind" : "remoteSourceControl", - "location" : "https://github.com/Moya/Moya", - "state" : { - "branch" : "master", - "revision" : "10a9dd1577c4de5135a29f99410863d2e9ee034a" - } - }, - { - "identity" : "reactiveswift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", - "state" : { - "revision" : "c43bae3dac73fdd3cb906bd5a1914686ca71ed3c", - "version" : "6.7.0" - } - }, - { - "identity" : "rxswift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ReactiveX/RxSwift.git", - "state" : { - "revision" : "9dcaa4b333db437b0fbfaf453fad29069044a8b4", - "version" : "6.6.0" - } - }, - { - "identity" : "sentry-cocoa", - "kind" : "remoteSourceControl", - "location" : "https://github.com/getsentry/sentry-cocoa.git", - "state" : { - "revision" : "b847a202a517a90763e8fd0656d8028aeee7b78d", - "version" : "8.20.0" - } - }, - { - "identity" : "snapkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SnapKit/SnapKit", - "state" : { - "revision" : "e74fe2a978d1216c3602b129447c7301573cc2d8", - "version" : "5.7.0" - } - }, - { - "identity" : "then", - "kind" : "remoteSourceControl", - "location" : "https://github.com/devxoul/Then", - "state" : { - "revision" : "d41ef523faef0f911369f79c0b96815d9dbb6d7a", - "version" : "3.0.0" - } - } - ], - "version" : 3 -} diff --git a/GEON-PPANG-iOS/Core/GBNetwork b/GEON-PPANG-iOS/Core/GBNetwork deleted file mode 160000 index 0ab05d69..00000000 --- a/GEON-PPANG-iOS/Core/GBNetwork +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0ab05d69105b226d75eea2fa5b929c1dbd032422 From 18dae14aeaeff0fe7523be2227cfdae3e2f1026b Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Sun, 30 Jun 2024 18:45:18 +0900 Subject: [PATCH 08/31] [Chore] #276 - re-added gbnetwork --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 55 ++ .../xcshareddata/swiftpm/Package.resolved | 105 ++++ .../GBNetwork.xcodeproj/project.pbxproj | 514 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../Core/GBNetwork/GBNetwork/APIClient.swift | 37 ++ .../GBNetwork/GBNetwork.docc/GBNetwork.md | 13 + .../Core/GBNetwork/GBNetwork/GBNetwork.h | 18 + .../GBNetwork/GBNetwork/GBNetworkError.swift | 52 ++ .../Core/GBNetwork/GBNetwork/HTTPHeader.swift | 49 ++ .../Core/GBNetwork/GBNetwork/HTTPMethod.swift | 17 + .../Core/GBNetwork/GBNetwork/HTTPTask.swift | 17 + .../GBNetwork/GBNetwork/RawResponse.swift | 28 + .../GBNetwork/GBNetwork/RequestType.swift | 57 ++ .../Core/GBNetwork/GBNetwork/Response.swift | 14 + .../GBNetwork/URLRequest+Encoding.swift | 40 ++ .../GBNetworkTests/GBNetworkTests.swift | 36 ++ 17 files changed, 1067 insertions(+) create mode 100644 GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift create mode 100755 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 0e1b8a6a..49d7a09c 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -138,6 +138,8 @@ 3E36D7D62A8E6AF000B2C1CC /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */; }; 3E36D7D82A8E6BC500B2C1CC /* FilterDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */; }; 3E36D7DA2A8E758A00B2C1CC /* FilterCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */; }; + 3E3DEBE42C31609500CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */; }; + 3E3DEBE52C31609500CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -261,6 +263,23 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3E3DEBE02C31608C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB332C3117A300CA5999; + remoteInfo = GBNetwork; + }; + 3E3DEBE22C31608C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB3D2C3117A400CA5999; + remoteInfo = GBNetworkTests; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -268,6 +287,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 3E3DEBE52C31609500CA5999 /* GBNetwork.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -400,6 +420,7 @@ 3E36D7D52A8E6AF000B2C1CC /* FilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; 3E36D7D72A8E6BC500B2C1CC /* FilterDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterDiffableDataSource.swift; sourceTree = ""; }; 3E36D7D92A8E758A00B2C1CC /* FilterCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterCellModel.swift; sourceTree = ""; }; + 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -534,6 +555,7 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, + 3E3DEBE42C31609500CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -1173,6 +1195,15 @@ name = Frameworks; sourceTree = ""; }; + 3E3DEBDC2C31608C00CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */, + 3E3DEBE32C31608C00CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1249,6 +1280,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( + 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1943,6 +1975,12 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3E3DEBDC2C31608C00CA5999 /* Products */; + ProjectRef = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -1950,6 +1988,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = GBNetwork.framework; + remoteRef = 3E3DEBE02C31608C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3E3DEBE32C31608C00CA5999 /* GBNetworkTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GBNetworkTests.xctest; + remoteRef = 3E3DEBE22C31608C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; diff --git a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..1b2650ff --- /dev/null +++ b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,105 @@ +{ + "originHash" : "a32b0a1c0ad6f6a91a39529043231e700bfb3a573e73a0172a5e40c9106b8bba", + "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire.git", + "state" : { + "revision" : "3dc6a42c7727c49bf26508e29b0a0b35f9c7e1ad", + "version" : "5.8.1" + } + }, + { + "identity" : "amplitude-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/amplitude/Amplitude-iOS", + "state" : { + "branch" : "main", + "revision" : "82fc62448292c13fa0a6b0b11c4524df83fd3f3b" + } + }, + { + "identity" : "analytics-connector-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/amplitude/analytics-connector-ios.git", + "state" : { + "revision" : "e2ca17ac735bcbc48b13062484541702ef45153d", + "version" : "1.0.3" + } + }, + { + "identity" : "kakao-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kakao/kakao-ios-sdk", + "state" : { + "revision" : "ae3c60cbd4e3b348775f8c766e5b908fa1e66c5a", + "version" : "2.20.0" + } + }, + { + "identity" : "kingfisher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/onevcat/Kingfisher.git", + "state" : { + "revision" : "5b92f029fab2cce44386d28588098b5be0824ef5", + "version" : "7.11.0" + } + }, + { + "identity" : "moya", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Moya/Moya", + "state" : { + "branch" : "master", + "revision" : "10a9dd1577c4de5135a29f99410863d2e9ee034a" + } + }, + { + "identity" : "reactiveswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", + "state" : { + "revision" : "c43bae3dac73fdd3cb906bd5a1914686ca71ed3c", + "version" : "6.7.0" + } + }, + { + "identity" : "rxswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveX/RxSwift.git", + "state" : { + "revision" : "9dcaa4b333db437b0fbfaf453fad29069044a8b4", + "version" : "6.6.0" + } + }, + { + "identity" : "sentry-cocoa", + "kind" : "remoteSourceControl", + "location" : "https://github.com/getsentry/sentry-cocoa.git", + "state" : { + "revision" : "b847a202a517a90763e8fd0656d8028aeee7b78d", + "version" : "8.20.0" + } + }, + { + "identity" : "snapkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SnapKit/SnapKit", + "state" : { + "revision" : "e74fe2a978d1216c3602b129447c7301573cc2d8", + "version" : "5.7.0" + } + }, + { + "identity" : "then", + "kind" : "remoteSourceControl", + "location" : "https://github.com/devxoul/Then", + "state" : { + "revision" : "d41ef523faef0f911369f79c0b96815d9dbb6d7a", + "version" : "3.0.0" + } + } + ], + "version" : 3 +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj new file mode 100644 index 00000000..0e332b8a --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 3E3DEB382C3117A400CA5999 /* GBNetwork.docc in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */; }; + 3E3DEB3E2C3117A400CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */; }; + 3E3DEB432C3117A400CA5999 /* GBNetworkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */; }; + 3E3DEB442C3117A400CA5999 /* GBNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E3DEB362C3117A300CA5999 /* GBNetwork.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3E3DEB562C3117F600CA5999 /* GBNetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */; }; + 3E3DEB572C3117F600CA5999 /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */; }; + 3E3DEB582C3117F600CA5999 /* URLRequest+Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */; }; + 3E3DEB592C3117F600CA5999 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB502C3117F600CA5999 /* Response.swift */; }; + 3E3DEB5B2C3117F600CA5999 /* RequestType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB522C3117F600CA5999 /* RequestType.swift */; }; + 3E3DEB5C2C3117F600CA5999 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */; }; + 3E3DEB5D2C3117F600CA5999 /* HTTPTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */; }; + 3E3DEB5E2C3117F600CA5999 /* HTTPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */; }; + 3E3DEB9C2C315DE000CA5999 /* RawResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3E3DEB3F2C3117A400CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEB2A2C3117A300CA5999 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E3DEB322C3117A300CA5999; + remoteInfo = GBNetwork; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GBNetwork.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E3DEB362C3117A300CA5999 /* GBNetwork.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GBNetwork.h; sourceTree = ""; }; + 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = GBNetwork.docc; sourceTree = ""; }; + 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GBNetworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GBNetworkTests.swift; sourceTree = ""; }; + 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GBNetworkError.swift; sourceTree = ""; }; + 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIClient.swift; sourceTree = ""; }; + 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URLRequest+Encoding.swift"; sourceTree = ""; }; + 3E3DEB502C3117F600CA5999 /* Response.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; + 3E3DEB522C3117F600CA5999 /* RequestType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestType.swift; sourceTree = ""; }; + 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; + 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPTask.swift; sourceTree = ""; }; + 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPHeader.swift; sourceTree = ""; }; + 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawResponse.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3E3DEB302C3117A300CA5999 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB3A2C3117A400CA5999 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB3E2C3117A400CA5999 /* GBNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3E3DEB292C3117A300CA5999 = { + isa = PBXGroup; + children = ( + 3E3DEB352C3117A300CA5999 /* GBNetwork */, + 3E3DEB412C3117A400CA5999 /* GBNetworkTests */, + 3E3DEB342C3117A300CA5999 /* Products */, + ); + sourceTree = ""; + }; + 3E3DEB342C3117A300CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */, + 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 3E3DEB352C3117A300CA5999 /* GBNetwork */ = { + isa = PBXGroup; + children = ( + 3E3DEB362C3117A300CA5999 /* GBNetwork.h */, + 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */, + 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */, + 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */, + 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */, + 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */, + 3E3DEB522C3117F600CA5999 /* RequestType.swift */, + 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */, + 3E3DEB502C3117F600CA5999 /* Response.swift */, + 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */, + 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */, + ); + path = GBNetwork; + sourceTree = ""; + }; + 3E3DEB412C3117A400CA5999 /* GBNetworkTests */ = { + isa = PBXGroup; + children = ( + 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */, + ); + path = GBNetworkTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3E3DEB2E2C3117A300CA5999 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB442C3117A400CA5999 /* GBNetwork.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3E3DEB322C3117A300CA5999 /* GBNetwork */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E3DEB472C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetwork" */; + buildPhases = ( + 3E3DEB2E2C3117A300CA5999 /* Headers */, + 3E3DEB2F2C3117A300CA5999 /* Sources */, + 3E3DEB302C3117A300CA5999 /* Frameworks */, + 3E3DEB312C3117A300CA5999 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GBNetwork; + productName = GBNetwork; + productReference = 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */; + productType = "com.apple.product-type.framework"; + }; + 3E3DEB3C2C3117A400CA5999 /* GBNetworkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E3DEB4A2C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetworkTests" */; + buildPhases = ( + 3E3DEB392C3117A400CA5999 /* Sources */, + 3E3DEB3A2C3117A400CA5999 /* Frameworks */, + 3E3DEB3B2C3117A400CA5999 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3E3DEB402C3117A400CA5999 /* PBXTargetDependency */, + ); + name = GBNetworkTests; + productName = GBNetworkTests; + productReference = 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3E3DEB2A2C3117A300CA5999 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 3E3DEB322C3117A300CA5999 = { + CreatedOnToolsVersion = 15.4; + }; + 3E3DEB3C2C3117A400CA5999 = { + CreatedOnToolsVersion = 15.4; + }; + }; + }; + buildConfigurationList = 3E3DEB2D2C3117A300CA5999 /* Build configuration list for PBXProject "GBNetwork" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3E3DEB292C3117A300CA5999; + productRefGroup = 3E3DEB342C3117A300CA5999 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3E3DEB322C3117A300CA5999 /* GBNetwork */, + 3E3DEB3C2C3117A400CA5999 /* GBNetworkTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3E3DEB312C3117A300CA5999 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB3B2C3117A400CA5999 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3E3DEB2F2C3117A300CA5999 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB5E2C3117F600CA5999 /* HTTPHeader.swift in Sources */, + 3E3DEB562C3117F600CA5999 /* GBNetworkError.swift in Sources */, + 3E3DEB382C3117A400CA5999 /* GBNetwork.docc in Sources */, + 3E3DEB9C2C315DE000CA5999 /* RawResponse.swift in Sources */, + 3E3DEB5C2C3117F600CA5999 /* HTTPMethod.swift in Sources */, + 3E3DEB582C3117F600CA5999 /* URLRequest+Encoding.swift in Sources */, + 3E3DEB5D2C3117F600CA5999 /* HTTPTask.swift in Sources */, + 3E3DEB572C3117F600CA5999 /* APIClient.swift in Sources */, + 3E3DEB592C3117F600CA5999 /* Response.swift in Sources */, + 3E3DEB5B2C3117F600CA5999 /* RequestType.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB392C3117A400CA5999 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB432C3117A400CA5999 /* GBNetworkTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3E3DEB402C3117A400CA5999 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E3DEB322C3117A300CA5999 /* GBNetwork */; + targetProxy = 3E3DEB3F2C3117A400CA5999 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3E3DEB452C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 3E3DEB462C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3E3DEB482C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = S9G6YGQ76H; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetwork"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3E3DEB492C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = S9G6YGQ76H; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetwork"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 3E3DEB4B2C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S9G6YGQ76H; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetworkTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3E3DEB4C2C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S9G6YGQ76H; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetworkTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3E3DEB2D2C3117A300CA5999 /* Build configuration list for PBXProject "GBNetwork" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB452C3117A400CA5999 /* Debug */, + 3E3DEB462C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3E3DEB472C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetwork" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB482C3117A400CA5999 /* Debug */, + 3E3DEB492C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3E3DEB4A2C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB4B2C3117A400CA5999 /* Debug */, + 3E3DEB4C2C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3E3DEB2A2C3117A300CA5999 /* Project object */; +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift new file mode 100644 index 00000000..402fd33f --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift @@ -0,0 +1,37 @@ +// +// APIClient.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public final class APIClient { + + public init() {} + + public func send( + _ request: Request + ) async throws -> RawResponse { + let configuration = URLSessionConfiguration.default + let session = URLSession(configuration: configuration) + + let (data, urlResponse) = try await session.data(for: request.toURLRequest()) + + guard let httpResponse = urlResponse as? HTTPURLResponse else { + throw GBNetworkError.decodingFailure(.httpDecodingError) + } + + switch httpResponse.statusCode { + case 200..<300: + return .init(data: data, httpResponse: httpResponse) + case 400..<500: + throw GBNetworkError.responseFailure(.clientError(httpResponse)) + case 500..<600: + throw GBNetworkError.responseFailure(.serverError(httpResponse)) + default: + throw GBNetworkError.responseFailure(.invalidError(httpResponse)) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md new file mode 100755 index 00000000..c81ecc33 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md @@ -0,0 +1,13 @@ +# ``GBNetwork`` + +Summary + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` \ No newline at end of file diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h new file mode 100644 index 00000000..d8191aaa --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h @@ -0,0 +1,18 @@ +// +// GBNetwork.h +// GBNetwork +// +// Created by 이성민 on 6/30/24. +// + +#import + +//! Project version number for GBNetwork. +FOUNDATION_EXPORT double GBNetworkVersionNumber; + +//! Project version string for GBNetwork. +FOUNDATION_EXPORT const unsigned char GBNetworkVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift new file mode 100644 index 00000000..22d83625 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift @@ -0,0 +1,52 @@ +// +// GBNetworkError.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum GBNetworkError: Error { + + // MARK: - Request related errors + + /// Creating `URL` from `String` failure + case urlCreationFailure(urlString: String) + + /// Encoding to `URLRequest` failure + case requestEncodingFailure(EncodingFailureReason) + + // MARK: - Response related errors + + /// Failure received from response + case responseFailure(ResponseFailureReason) + + /// Decoding `Data` to response type failure + case decodingFailure(DecodingFailureReason) + + /// Failure other than the failures above + case unknownFailure(description: String) +} + + +public extension GBNetworkError { + + enum EncodingFailureReason { + case pathError(String) + case jsonError(String) + } + + /// detailed reason why `.responseFailure` occurred + enum ResponseFailureReason { + case clientError(HTTPURLResponse) + case serverError(HTTPURLResponse) + case invalidError(HTTPURLResponse) + } + + enum DecodingFailureReason { + case httpDecodingError + case dtoDecodingError + } +} + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift new file mode 100644 index 00000000..7131816f --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift @@ -0,0 +1,49 @@ +// +// HTTPHeader.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public struct HTTPHeader { + private(set) var headers: [HTTPHeaderField] = [] + + public init(headers: [HTTPHeaderField]) { + self.headers = headers + } +} + +extension HTTPHeader { + var fields: [String: String] { + .init(uniqueKeysWithValues: headers.map { ($0.key, $0.value) }) + } +} + +public struct HTTPHeaderField { + let key: String + let value: String +} + +public extension HTTPHeaderField { + static func contentType(value: String) -> HTTPHeaderField { + .init(key: "Content-Type", value: value) + } + + static func accessToken(value: String) -> HTTPHeaderField { + .init(key: "Authorization", value: "Bearer \(value)") + } + + static func refreshToken(value: String) -> HTTPHeaderField { + .init(key: "Authorization-refresh", value: "Bearer \(value)") + } + + static func appleRefreshToken(value: String) -> HTTPHeaderField { + .init(key: "Apple-refresh", value: value) + } + + static func platformToken(value: String) -> HTTPHeaderField { + .init(key: "Platform-Token", value: value) + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift new file mode 100644 index 00000000..2b707d9b --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift @@ -0,0 +1,17 @@ +// +// HTTPMethod.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum HTTPMethod: String { + /// HTTP `GET` method + case GET + /// HTTP `POST` method + case POST + /// HTTP `DELETE` method + case DELETE +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift new file mode 100644 index 00000000..b1119856 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift @@ -0,0 +1,17 @@ +// +// HTTPTask.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum HTTPTask { + /// plain request + case requestPlain + /// request with query parameters + case requestQuery(_ query: [String: Any]) + /// request with encodable body + case requestEncodable(_ body: Encodable) +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift new file mode 100644 index 00000000..dd0b1aa9 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift @@ -0,0 +1,28 @@ +// +// RawResponse.swift +// GBNetwork +// +// Created by 이성민 on 6/30/24. +// + +import Foundation + +public struct RawResponse { + public let data: Data + public let httpResponse: HTTPURLResponse + + init(data: Data, httpResponse: HTTPURLResponse) { + self.data = data + self.httpResponse = httpResponse + } +} + +extension RawResponse { + public func decode(to type: DTO.Type) throws -> Response { + do { + return try JSONDecoder().decode(Response.self, from: self.data) + } catch { + throw GBNetworkError.decodingFailure(.dtoDecodingError) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift new file mode 100644 index 00000000..c069831a --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift @@ -0,0 +1,57 @@ +// +// RequestType.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public protocol RequestType { + + /// Request를 보내는 Base URL + var baseURL: String { get } + + /// Base URL 뒤에 붙는 URL Path + var path: String { get } + + /// 실제로 사용하는 HTTP Method만 정의 - Get, Post, Delete + /// + /// - Request의 HTTP Method: + /// 현재는 GET, POST, DELETE만 사용하기 때문에 세 가지만 설정 + /// + /// - computed property로 한 이유는 encodable에 걸리지 않기 때문 + var method: HTTPMethod { get } + + /// 어떤 방식으로 Request를 보낼지에 대한 정보 + /// + /// - `.requestPlain` - 추가적인 body 또는 query 없이 요청 + /// - `.requestQuery(_ [String: Any])` - url path 뒤에 query 추가하여 요청 + /// - `.requestEncodable(_ : Encodable)` - encodable 한 body와 함께 요청 + var task: HTTPTask { get } + + /// Request 마다 필요한 Header Fields + var headers: HTTPHeader { get } +} + +extension RequestType { + + func toURLRequest() throws -> URLRequest { + guard let url = URL(string: baseURL + path) else { + throw URLError(.badURL) + } + + var urlRequest = URLRequest(url: url) + urlRequest.httpMethod = self.method.rawValue + urlRequest.allHTTPHeaderFields = self.headers.fields + + switch task { + case .requestPlain: + return urlRequest + case let .requestQuery(queries): + return try urlRequest.encode(queries: queries) + case let .requestEncodable(body): + return try urlRequest.encode(body: body) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift new file mode 100644 index 00000000..1db359d1 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift @@ -0,0 +1,14 @@ +// +// ResponseType.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public struct Response: Decodable { + public let code: Int + public let message: String + public let data: DTO +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift new file mode 100644 index 00000000..d51c16be --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift @@ -0,0 +1,40 @@ +// +// URLRequest+Encoding.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +extension URLRequest { + func encode(queries: [String: Any]) throws -> URLRequest { + guard let url = self.url else { + throw GBNetworkError.requestEncodingFailure(.pathError("missing url")) + } + + var components = URLComponents(string: url.absoluteString) + components?.queryItems = queries.map(toQueryItem) + + guard let encodedURL = components?.url else { + throw GBNetworkError.requestEncodingFailure(.pathError("query encoding fail")) + } + return .init(url: encodedURL) + } + + func encode(body: Encodable) throws -> URLRequest { + do { + var request = self + request.httpBody = try JSONEncoder().encode(body) + return request + } catch { + throw GBNetworkError.requestEncodingFailure(.jsonError("incorrect body type")) + } + } +} + +private extension URLRequest { + func toQueryItem(_ query: (key: String, value: Any)) -> URLQueryItem { + .init(name: query.key, value: query.value as? String) + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift new file mode 100644 index 00000000..200e9da3 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift @@ -0,0 +1,36 @@ +// +// GBNetworkTests.swift +// GBNetworkTests +// +// Created by 이성민 on 6/30/24. +// + +import XCTest +@testable import GBNetwork + +final class GBNetworkTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} From 9c0c8d6ec4e56a6072103d686d3ad57d8b0ac24b Mon Sep 17 00:00:00 2001 From: seongmin221 Date: Tue, 9 Jul 2024 21:57:53 +0900 Subject: [PATCH 09/31] [Chore] #276 - fixed optional header --- GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift index 7131816f..74998033 100644 --- a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift @@ -10,8 +10,8 @@ import Foundation public struct HTTPHeader { private(set) var headers: [HTTPHeaderField] = [] - public init(headers: [HTTPHeaderField]) { - self.headers = headers + public init(headers: [HTTPHeaderField?]) { + self.headers = headers.compactMap { $0 } } } @@ -46,4 +46,9 @@ public extension HTTPHeaderField { static func platformToken(value: String) -> HTTPHeaderField { .init(key: "Platform-Token", value: value) } + + static func optionalToken(value: String?) -> HTTPHeaderField? { + guard let value else { return nil } + return .init(key: "Authorization", value: value) + } } From 762214efd4fad47da3d3400f8a41dd2e34ab30af Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:04:37 +0900 Subject: [PATCH 10/31] =?UTF-8?q?[Feat]=20#275=20-=20BestRepository=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Repository/BestRepositoryImpl.swift | 60 +++++++++++++++++++ .../Domain/Interface/BestRepository.swift | 13 ++++ 2 files changed, 73 insertions(+) create mode 100644 GEON-PPANG-iOS/Data/Repository/BestRepositoryImpl.swift create mode 100644 GEON-PPANG-iOS/Domain/Interface/BestRepository.swift diff --git a/GEON-PPANG-iOS/Data/Repository/BestRepositoryImpl.swift b/GEON-PPANG-iOS/Data/Repository/BestRepositoryImpl.swift new file mode 100644 index 00000000..8cc0227e --- /dev/null +++ b/GEON-PPANG-iOS/Data/Repository/BestRepositoryImpl.swift @@ -0,0 +1,60 @@ +// +// BestRepository.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 6/29/24. +// + +import Foundation + +import GBNetwork + +final class BestRepositoryImpl: BestRepository { + + private let apiClient: APIClient = .init() + + func getBestBakeries() async throws -> [BestBakery] { + let rawResponse = try await apiClient.send(.getBestBakeries) + let response = try rawResponse.decode(to: [BestBakeryResponseDTO].self) + + switch response.code { + case 200..<300: + return response.data.map { $0.toDomain() } + case 401: + if response.message == MemberError.invalidToken.rawValue { + throw MemberError.invalidToken + } else if response.message == MemberError.expiredToken.rawValue { + throw MemberError.expiredToken + } else { throw MemberError.otherError } + default: + throw MemberError.otherError + } + } + + func getBestReviews() async throws -> [BestReview] { + let rawResponse = try await apiClient.send(.getBestReviews) + let response = try rawResponse.decode(to: [BestReviewResponseDTO].self) + + switch response.code { + case 200..<300: + return response.data.map { $0.toDomain() } + case 401: + if response.message == MemberError.invalidToken.rawValue { + throw MemberError.invalidToken + } else if response.message == MemberError.expiredToken.rawValue { + throw MemberError.expiredToken + } else { throw MemberError.otherError } + default: + throw MemberError.otherError + } + } +} + +enum MemberError: String, Error { + /// 유효하지 않은 토큰 ( 401 ) + case invalidToken = "엑세스 토큰이 없습니다" + /// 만료된 토큰 ( 401 ) + case expiredToken = "만료된 토큰입니다" + /// 그 외의 오류 ( 404, 500번대 ) + case otherError +} diff --git a/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift b/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift new file mode 100644 index 00000000..0f8c24bf --- /dev/null +++ b/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift @@ -0,0 +1,13 @@ +// +// BestRepository.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 7/9/24. +// + +import Foundation + +protocol BestRepository { + func getBestBakeries() async throws -> [BestBakery] + func getBestReviews() async throws -> [BestReview] +} From 0a80187062166fb4135eb019fa51f177bea4f260 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:04:57 +0900 Subject: [PATCH 11/31] =?UTF-8?q?[Feat]=20#275=20-=20Best=20Response=20DTO?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ResponseDTO/BestBakeryResponseDTO.swift | 58 +++++++++++++++++++ .../ResponseDTO/BestReviewResponseDTO.swift | 39 +++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift create mode 100644 GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestReviewResponseDTO.swift diff --git a/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift new file mode 100644 index 00000000..d0d657e8 --- /dev/null +++ b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift @@ -0,0 +1,58 @@ +// +// BestBakeryDTO.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 6/29/24. +// +import Foundation + +struct BestBakeryResponseDTO: Decodable { + + let bakeryID: Int + let bakeryName: String + let bakeryPicture: String + let isHACCP, isVegan, isNonGMO: Bool + let firstNearStation: String + let secondNearStation: String + let reviewCount, bookMarkCount: Int + + enum CodingKeys: String, CodingKey { + case bakeryID = "bakeryId" + case bakeryName + case bakeryPicture + case isHACCP, isVegan, isNonGMO + case firstNearStation, secondNearStation + case reviewCount + case bookMarkCount + } + +} + +extension BestBakeryResponseDTO { + + func toDomain() -> BestBakery { + let overview: BakeryOverview = .init( + id: bakeryID, + name: bakeryName, + image: bakeryPicture + ) + let certifications: Certifications = .init( + isHaccp: isHACCP, + isVegan: isVegan, + isNonGMO: isNonGMO + ) + let regions: Regions = .init( + firstRegion: firstNearStation, + secondRegion: secondNearStation + ) + + return BestBakery( + overview: overview, + certifications: certifications, + bookmarkCount: bookMarkCount, + reviewCount: reviewCount, + regions: regions + ) + } +} + diff --git a/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestReviewResponseDTO.swift b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestReviewResponseDTO.swift new file mode 100644 index 00000000..cc4edb1e --- /dev/null +++ b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestReviewResponseDTO.swift @@ -0,0 +1,39 @@ +// +// BestReviewDTO.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 6/29/24. +// + +import Foundation + +struct BestReviewResponseDTO: Decodable { + let bakeryID: Int + let bakeryName: String + let bakeryPicture: String + let isHACCP, isVegan, isNonGMO: Bool + let firstNearStation, secondNearStation: String + let reviewCount: Int + let reviewText: String + let firstMaxRecommendKeyword: String + let secondMaxRecommendKeyword: String? + let bookMarkCount: Int + + enum CodingKeys: String, CodingKey { + case bakeryID = "bakeryId" + case bakeryName, bakeryPicture, isHACCP, isVegan, isNonGMO, firstNearStation, secondNearStation, reviewCount, reviewText, firstMaxRecommendKeyword, secondMaxRecommendKeyword, bookMarkCount + } +} + +extension BestReviewResponseDTO { + + func toDomain() -> BestReview { + let overview: BakeryOverview = .init(id: bakeryID, name: bakeryName, image: bakeryPicture) + + return BestReview(overview: overview, + reviewOverview: reviewText, + recommendKeywords: [firstMaxRecommendKeyword, secondNearStation], + bookmarkCount: bookMarkCount, + reviewCount: reviewCount) + } +} From 1aa81b7c55ae48202ebf19f96c6074416cd8ea19 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:05:21 +0900 Subject: [PATCH 12/31] =?UTF-8?q?[Feat]=20#275=20-=20HomeUseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/UseCase/HomeUseCase.swift | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift diff --git a/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift new file mode 100644 index 00000000..81a470fe --- /dev/null +++ b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift @@ -0,0 +1,46 @@ +// +// HomeUseCase.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 6/29/24. +// + +import Foundation +import Combine + +protocol HomeUseCase { + func fetchBestBakeries() async throws -> [BestBakery] + func fetchBestReviews() async throws -> [BestReview] +} + +final class HomeUseCaseImpl: HomeUseCase { + let bestRepository: BestRepository + + init(bestRepository: BestRepository) { + self.bestRepository = bestRepository + } + + func fetchBestBakeries() async throws -> [BestBakery] { + do { + return try await bestRepository.getBestBakeries() + } + catch MemberError.expiredToken { + throw MemberError.expiredToken + } + catch MemberError.invalidToken { + throw MemberError.invalidToken + } + } + + func fetchBestReviews() async throws -> [BestReview] { + do { + return try await bestRepository.getBestReviews() + } + catch MemberError.expiredToken { + throw MemberError.expiredToken + } + catch MemberError.invalidToken { + throw MemberError.invalidToken + } + } +} From 89a8fc8537ce31815d7813f24e54a736b1c995ab Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:05:34 +0900 Subject: [PATCH 13/31] =?UTF-8?q?[Feat]=20#275=20-=20HomeViewModel=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/Home/ViewModel/HomeViewModel.swift | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift new file mode 100644 index 00000000..d103f8d5 --- /dev/null +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift @@ -0,0 +1,85 @@ +// +// HomeViewModel.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 7/9/24. +// + + +import Foundation +import Combine + +final class HomeViewModel: ViewModelType { + + struct Input { + let viewWillAppear: PassthroughSubject + init(viewWillAppear: PassthroughSubject) { + self.viewWillAppear = viewWillAppear + } + } + + struct Output { + let best: AnyPublisher<([BestBakery], [BestReview]), Error> + } + + // MARK: - Property + + private let usecase: HomeUseCase + private var cancellable: Set = Set() + + init(usecase: HomeUseCase) { + self.usecase = usecase + } + + // MARK: - func + + func transform(_ input: Input) -> Output { + let bakery = input.viewWillAppear + .compactMap { [weak self] in self } + .flatMap { _ -> AnyPublisher<[BestBakery], Error> in + Future<[BestBakery], Error> { promise in + Task { + do { + let bakery = try await self.fetchBestBakery() + promise(.success(bakery)) + } catch { + promise(.failure(error)) + } + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + + let review = input.viewWillAppear + .compactMap { [weak self] in self } + .flatMap { _ -> AnyPublisher<[BestReview], Error> in + return Future<[BestReview], Error> { promise in + Task { + do { + let review = try await self.fetchBestReview() + promise(.success(review)) + } catch { + promise(.failure(error)) + } + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + + let best = Publishers.CombineLatest(bakery, review) + + return Output(best: best.eraseToAnyPublisher()) + } +} + +extension HomeViewModel { + private func fetchBestBakery() async throws -> [BestBakery] { + return try await self.usecase.fetchBestBakeries() + } + + private func fetchBestReview() async throws -> [BestReview] { + return try await self.usecase.fetchBestReviews() + } +} From 9df3023d06a713805d8b032269894f13dcdca5cc Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:06:03 +0900 Subject: [PATCH 14/31] =?UTF-8?q?[Fix]=20#275=20-=20Home=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20UI=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/HomeBakeryCollectionViewCell.swift | 99 ++++++-- .../Home/HomeReviewCollectionViewCell.swift | 14 +- .../ViewController/HomeViewController.swift | 10 +- .../NewHomeViewController.swift | 238 ++++++++++++++++++ 4 files changed, 337 insertions(+), 24 deletions(-) create mode 100644 GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift index 52a7aed9..f7bc3059 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift @@ -17,6 +17,7 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { private let bakeryImage = UIImageView() private let markStackView = MarkStackView() + // private var markStackView: GBStackView private let bakeryTitle = UILabel() private let reviewCount = IconWithTextView(.reviews) private let bookmarkCount = IconWithTextView(.bookmark) @@ -101,10 +102,10 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { $0.clipsToBounds = true } - markStackView.do { - $0.configureIconImage(.bigHACCPMark, .bigVeganMark, .bigGMOMark) - } - +// markStackView.do { +// $0.configureIconImage(.bigHACCPMark, .bigVeganMark, .bigGMOMark) +// } +// bakeryTitle.do { $0.numberOfLines = 1 $0.basic(font: .bodyB1!, color: .gbbGray700!) @@ -115,23 +116,91 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { // MARK: - Custom Method - func configureCellUI(data: HomeBestBakeryResponseDTO) { + func configureCellUI(data: BestBakery) { - let url = URL(string: data.bakeries.picture) + let url = URL(string: data.overview.image) bakeryImage.kf.setImage(with: url, placeholder: UIImage.loading_large) - bakeryTitle.setLineHeight(by: 1.08, with: data.bakeries.name) + bakeryTitle.setLineHeight(by: 1.08, with: data.overview.name) bakeryTitle.lineBreakMode = .byTruncatingTail - - bookmarkCount.configureHomeCell(count: data.bakeries.bookmarkCount) - reviewCount.configureHomeCell(count: data.bakeries.reviewCount) - markStackView.getMarkStatus(data.bakeries.mark.isHACCP, - data.bakeries.mark.isVegan, - data.bakeries.mark.isNonGMO) - if data.bakeries.station.second == "" { + bookmarkCount.configureHomeCell(count: data.bookmarkCount) + reviewCount.configureHomeCell(count: data.reviewCount) + // markStackView = GBStackView(type: .big, data: [data.certifications.isHaccp, +// data.certifications.isVegan, +// data.certifications.isNonGMO +// ]) +// markStackView.getMarkStatus(data.certifications.isHaccp, +// data.certifications.isVegan, +// data.certifications.isNonGMO) + + if data.regions.secondRegion == "" { regionStackView.removeSecondRegion() } - regionStackView.configureRegion(data.bakeries.station) + regionStackView.configureRegion(data.regions) + } +} + + +enum GBStackType { + case big + case small + + var images: [UIImage]{ + switch self { + case .big: + return [.bigHACCPMark, .bigVeganMark, .bigGMOMark] + case .small: + return [.smallHACCPMark, .smallVeganMark, .smallGMOMark] + } + } + + var size: Int { + switch self { + case .big: + return 28 + case .small: + return 24 + } + } +} + +final class GBStackView: UIStackView { + + init(type: GBStackType, data: [Bool]) { + super.init(frame: .zero) + + setUI() + createCells(type: type, from: data).forEach { view in + self.addArrangedSubview(view) + } + } + + required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func createCells(type: GBStackType, from data: [Bool]) -> [UIImageView] { + let images = type.images + var imageIndex = 0 + + return data.compactMap { isCertified in + defer { imageIndex += 1 } + guard isCertified, imageIndex < images.count else { return nil } + let imageView = UIImageView(image: images[imageIndex]) + imageView.contentMode = .topLeft + imageView.snp.makeConstraints { $0.size.equalTo(type.size) } + return imageView + } + } + + private func setLayout() { + + } + + private func setUI() { + self.axis = .horizontal + self.spacing = -8 } } + diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift index c205f1e9..a903831f 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift @@ -121,20 +121,20 @@ final class HomeReviewCollectionViewCell: UICollectionViewCell { } - func configureCellUI(data: HomeBestReviewResponseDTO) { + func configureCellUI(data: BestReview) { - let url = URL(string: data.reviews.picture) + let url = URL(string: data.overview.image) bakeryImage.kf.setImage(with: url, placeholder: UIImage.loading_large) - reviewTitle.setLineHeight(by: 1.14, with: "\"\(data.text)\"") + reviewTitle.setLineHeight(by: 1.14, with: "\"\(data.reviewOverview)\"") reviewTitle.lineBreakMode = .byTruncatingTail - bakeryTitle.setLineHeight(by: 1.08, with: data.reviews.name) + bakeryTitle.setLineHeight(by: 1.08, with: data.overview.name) bakeryTitle.lineBreakMode = .byTruncatingTail - reviewCount.configureHomeCell(count: data.reviews.reviewCount) - bookmarkCount.configureHomeCell(count: data.reviews.bookmarkCount) + reviewCount.configureHomeCell(count: data.reviewCount) + bookmarkCount.configureHomeCell(count: data.bookmarkCount) - keywords = data.keywords.keywords + keywords = data.recommendKeywords collectionView.reloadData() } } diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift index 5e4d24bd..c5eaad3e 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift @@ -147,11 +147,11 @@ final class HomeViewController: BaseViewController { switch item { case .bakery(let data): let cell: HomeBakeryCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - cell.configureCellUI(data: data) + // cell.configureCellUI(data: data) return cell case .reviews(let data): let cell: HomeReviewCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - cell.configureCellUI(data: data) + // cell.configureCellUI(data: data) return cell case .bottom: let cell: HomeBottomCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) @@ -330,3 +330,9 @@ extension HomeViewController { } } } + + +final class HomeCompositionalLayout: UICollectionViewCompositionalLayout { + + +} diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift new file mode 100644 index 00000000..f68bda71 --- /dev/null +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -0,0 +1,238 @@ +// +// NewHomeViewController.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 7/9/24. +// + +import Combine + +import UIKit + +final class NewHomeViewController: UIViewController { + + // MARK: - Property + + private lazy var safeArea = self.view.safeAreaLayoutGuide + + private let viewModel: any ViewModelType + private var cancelBag: Set = Set() + + private let viewWillAppearPublisher: PassthroughSubject = PassthroughSubject() + + private var bakeryList: [BestBakery] = [] + private var reviewList: [BestReview] = [] + + // MARK: - UI Property + + private let topView: HomeTopView = { + let view = HomeTopView() + return view + }() + + private lazy var collectionView: UICollectionView = { + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout()) + collectionView.showsVerticalScrollIndicator = false + collectionView.backgroundColor = .gbbBackground1 + collectionView.registerCells(cells: [HomeBakeryCollectionViewCell.self, + HomeReviewCollectionViewCell.self, + HomeBottomCollectionViewCell.self]) + collectionView.register(header: HomeHeaderView.self) + collectionView.dataSource = self + return collectionView + }() + + // MARK: - init + + init(viewModel: any ViewModelType) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Life cycle + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + viewWillAppearPublisher.send() + } + + override func viewDidLoad() { + super.viewDidLoad() + + setLayout() + setUI() + setViewModel() + } + + private func setLayout() { + + view.addSubview(topView) + topView.snp.makeConstraints { + $0.top.equalToSuperview().offset(heightConsideringNotch(44)) + $0.directionalHorizontalEdges.equalTo(safeArea) + $0.height.equalTo(200) + } + + view.addSubview(collectionView) + collectionView.snp.makeConstraints { + $0.top.equalTo(topView.snp.bottom) + $0.directionalHorizontalEdges.equalTo(safeArea) + $0.bottom.equalToSuperview() + } + } + + private func setUI() { + self.view.backgroundColor = .white + } + + private func setViewModel() { + let output = transformedOutput() + self.bindOutputToViewModel(output) + } + + private func transformedOutput() -> HomeViewModel.Output? { + guard let viewModel = self.viewModel as? HomeViewModel + else { return nil } + let input = HomeViewModel.Input( + viewWillAppear: self.viewWillAppearPublisher + ) + return viewModel.transform(input) + } + + private func bindOutputToViewModel(_ output: HomeViewModel.Output?) { + guard let output else { return } + + output.best + .receive(on: RunLoop.main) + .sink { err in + print("error:\(err)") + } receiveValue: { [weak self] bakery, review in + dump(bakery) + self?.updateList(bakery: bakery, review: review) + } + .store(in: &self.cancelBag) + } + + private func updateList(bakery: [BestBakery], review: [BestReview]) { + self.bakeryList = bakery + self.reviewList = review + self.collectionView.reloadData() + } +} + +extension NewHomeViewController: UICollectionViewDataSource { + + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 3 + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + switch section { + case 0: + return bakeryList.count + case 1: + return reviewList.count + default: + return 1 + } + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + switch indexPath.section { + case 0: + let cell: HomeBakeryCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + let item = self.bakeryList[indexPath.item] + cell.configureCellUI(data: item) + return cell + case 1: + let cell: HomeReviewCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + let item = self.reviewList[indexPath.item] + cell.configureCellUI(data: item) + return cell + case 2: + let cell: HomeBottomCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + return cell + default: + return UICollectionViewCell() + } + } + + func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { + guard kind == UICollectionView.elementKindSectionHeader, + let header = collectionView.dequeueReusableSupplementaryView( + ofKind: kind, + withReuseIdentifier: HomeHeaderView.identifier, + for: indexPath + ) as? HomeHeaderView else { return UICollectionReusableView() } + + guard let title = Sections(rawValue: indexPath.section)?.title else { return UICollectionReusableView() } + // nickname + header.configureSectionHeaderTitle(nil, title) + return header + } +} + +extension NewHomeViewController { + private func layout() -> UICollectionViewCompositionalLayout { + + return UICollectionViewCompositionalLayout(sectionProvider: { [weak self] sectionIndex, _ in + switch sectionIndex { + case 0: + return self?.bestSection(headerSize: 49) + case 1: + return self?.bestSection(headerSize: 25) + default: + return self?.bottomSection() + } + }) + } + + private func bestSection(headerSize: CGFloat) -> NSCollectionLayoutSection { + + let itemGroupSize = NSCollectionLayoutSize(widthDimension: .absolute(convertByWidthRatio(192)), + heightDimension: .absolute(heightConsideringNotch(236))) + let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemGroupSize, subitems: [item]) + + let section = NSCollectionLayoutSection(group: group) + section.interGroupSpacing = 12 + section.orthogonalScrollingBehavior = .continuous + + let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), + heightDimension: .absolute(headerSize)) + let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .top) + section.contentInsets = NSDirectionalEdgeInsets(top: 24, + leading: 24, + bottom: 30, + trailing: 24) + + section.boundarySupplementaryItems = [header] + return section + } + + private func bottomSection() -> NSCollectionLayoutSection { + + let itemGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), + heightDimension: .absolute(72)) + let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) + + let group = NSCollectionLayoutGroup.vertical(layoutSize: itemGroupSize, + subitem: item, + count: 1) + let section = NSCollectionLayoutSection(group: group) + section.contentInsets = NSDirectionalEdgeInsets(top: 14, + leading: 24, + bottom: 30, + trailing: 24) + + return section + } +} From 9f5eacfe597b3dc6a8246ce3c71b7a2509e05394 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:10:10 +0900 Subject: [PATCH 15/31] =?UTF-8?q?[Fix]=20#275=20-=20region=20stackView=20U?= =?UTF-8?q?I=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Common/StackView/RegionStackView.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift b/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift index c4d78b50..d5ed3016 100644 --- a/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift +++ b/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift @@ -65,6 +65,13 @@ final class RegionStackView: UIStackView { setUI(!data.stations[1].isEmpty) } + func configureRegion(_ data: Regions) { + + regionFirstTag.text = data.firstRegion + regionSecondTag.text = data.secondRegion + setUI(((data.secondRegion?.isEmpty) != nil)) + } + func configureChipCornerRadius(_ radius: CGFloat) { [regionFirstTag, regionSecondTag].forEach { From fd7a9c2de729867ef73ef63034e3c23edef66b78 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 9 Jul 2024 22:12:20 +0900 Subject: [PATCH 16/31] =?UTF-8?q?[Add]=20#275=20-=20Network=20=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=9E=84=EC=9B=8C=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 139 ++++- .../xcshareddata/swiftpm/Package.resolved | 29 +- .../GBNetwork.xcodeproj/project.pbxproj | 514 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../Core/GBNetwork/GBNetwork/APIClient.swift | 37 ++ .../GBNetwork/GBNetwork.docc/GBNetwork.md | 13 + .../Core/GBNetwork/GBNetwork/GBNetwork.h | 18 + .../GBNetwork/GBNetwork/GBNetworkError.swift | 52 ++ .../Core/GBNetwork/GBNetwork/HTTPHeader.swift | 49 ++ .../Core/GBNetwork/GBNetwork/HTTPMethod.swift | 17 + .../Core/GBNetwork/GBNetwork/HTTPTask.swift | 17 + .../GBNetwork/GBNetwork/RawResponse.swift | 28 + .../GBNetwork/GBNetwork/RequestType.swift | 57 ++ .../Core/GBNetwork/GBNetwork/Response.swift | 14 + .../GBNetwork/URLRequest+Encoding.swift | 40 ++ .../GBNetworkTests/GBNetworkTests.swift | 36 ++ .../Network/InfrastructureDummy.swift | 17 - 18 files changed, 1040 insertions(+), 52 deletions(-) create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift create mode 100755 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift create mode 100644 GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift delete mode 100644 GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index cc90b6d4..cb36662a 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -29,6 +29,13 @@ 0915C1752A5C533900ACB8D4 /* HomeReviewCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0915C1742A5C533900ACB8D4 /* HomeReviewCollectionViewCell.swift */; }; 091AFD422ABD79380001DD02 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 091AFD412ABD79380001DD02 /* Settings.bundle */; }; 0924632F2A5BA0F200B6F65D /* HomeBakeryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0924632E2A5BA0F200B6F65D /* HomeBakeryCollectionViewCell.swift */; }; + 092698832C3CF2F200A9349D /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092698822C3CF2F200A9349D /* HomeViewModel.swift */; }; + 092698882C3CF93F00A9349D /* BestReviewResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092698862C3CF93F00A9349D /* BestReviewResponseDTO.swift */; }; + 092698892C3CF93F00A9349D /* BestBakeryResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092698872C3CF93F00A9349D /* BestBakeryResponseDTO.swift */; }; + 0926988B2C3CF94C00A9349D /* BestEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0926988A2C3CF94C00A9349D /* BestEndpoint.swift */; }; + 0926988F2C3CF96100A9349D /* BestRepositoryImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0926988E2C3CF96100A9349D /* BestRepositoryImpl.swift */; }; + 092698932C3CF98B00A9349D /* HomeUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092698922C3CF98B00A9349D /* HomeUseCase.swift */; }; + 092698952C3CFD3800A9349D /* BestRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092698942C3CFD3800A9349D /* BestRepository.swift */; }; 092EFCA42A6195D900E7C262 /* CommonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092EFCA32A6195D900E7C262 /* CommonTextView.swift */; }; 0930D25B2A928B8000A75C7E /* CertificationMarkResponseType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0930D25A2A928B8000A75C7E /* CertificationMarkResponseType.swift */; }; 0930D25D2A928BF200A75C7E /* NearStationResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0930D25C2A928BF200A75C7E /* NearStationResponseDTO.swift */; }; @@ -90,6 +97,7 @@ 09C6264E2A5B29F8002C8110 /* SearchEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C6264D2A5B29F8002C8110 /* SearchEnum.swift */; }; 09C626562A5B3572002C8110 /* HomeBestReviewResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C626552A5B3572002C8110 /* HomeBestReviewResponseDTO.swift */; }; 09C626582A5B4269002C8110 /* HomeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C626572A5B4269002C8110 /* HomeHeaderView.swift */; }; + 09C8C11E2C3CEFF2009C4213 /* NewHomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C8C11D2C3CEFF2009C4213 /* NewHomeViewController.swift */; }; 09CA3EF82A5676AA0063897A /* CommonButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CA3EF72A5676AA0063897A /* CommonButton.swift */; }; 09CA3EFC2A569E4A0063897A /* URLConstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CA3EFB2A569E4A0063897A /* URLConstant.swift */; }; 09CD07902A620D7D00A078DE /* NickNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CD078F2A620D7D00A078DE /* NickNameViewController.swift */; }; @@ -167,6 +175,8 @@ 3E3DE9E52C25AF7600CA5999 /* ReviewPercentage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DE9E42C25AF7600CA5999 /* ReviewPercentage.swift */; }; 3E3DE9E72C25AF8500CA5999 /* Reviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DE9E62C25AF8500CA5999 /* Reviews.swift */; }; 3E3DE9E92C25AFA100CA5999 /* Review.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DE9E82C25AFA100CA5999 /* Review.swift */; }; + 3E3DEBE42C31609500CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */; }; + 3E3DEBE52C31609500CA5999 /* GBNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3E452B672A60E68000EA456D /* MyPageResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */; }; 3E452B692A60FF7900EA456D /* MyPageCollectionViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */; }; 3E452B6B2A614AAE00EA456D /* ImageWithSubtitleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */; }; @@ -254,7 +264,6 @@ 3EF9F8AE2BBD118700F3E366 /* DummyUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8AD2BBD118700F3E366 /* DummyUseCase.swift */; }; 3EF9F8B02BBD118C00F3E366 /* DummyInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8AF2BBD118C00F3E366 /* DummyInterface.swift */; }; 3EF9F8B72BBD141600F3E366 /* DummyEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8B62BBD141600F3E366 /* DummyEndpoint.swift */; }; - 3EF9F8BB2BBD228C00F3E366 /* InfrastructureDummy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */; }; 3EFA97862A5EBCA9002E70FA /* LineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFA97852A5EBCA9002E70FA /* LineView.swift */; }; 3EFA97882A5EBCED002E70FA /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFA97872A5EBCED002E70FA /* CustomNavigationBar.swift */; }; DF483ACC2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF483ACB2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift */; }; @@ -289,6 +298,37 @@ DFFBE3872AB8B4C100D27548 /* DetailReasonTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFBE3862AB8B4C100D27548 /* DetailReasonTextView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3E3DEBE02C31608C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB332C3117A300CA5999; + remoteInfo = GBNetwork; + }; + 3E3DEBE22C31608C00CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3E3DEB3D2C3117A400CA5999; + remoteInfo = GBNetworkTests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 3E3DEA002C26981200CA5999 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3E3DEBE52C31609500CA5999 /* GBNetwork.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 0905561F2A51DB2C00752067 /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 090556212A51DB3300752067 /* UIFont+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+.swift"; sourceTree = ""; }; @@ -309,6 +349,13 @@ 0915C1742A5C533900ACB8D4 /* HomeReviewCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeReviewCollectionViewCell.swift; sourceTree = ""; }; 091AFD412ABD79380001DD02 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 0924632E2A5BA0F200B6F65D /* HomeBakeryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeBakeryCollectionViewCell.swift; sourceTree = ""; }; + 092698822C3CF2F200A9349D /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; + 092698862C3CF93F00A9349D /* BestReviewResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BestReviewResponseDTO.swift; sourceTree = ""; }; + 092698872C3CF93F00A9349D /* BestBakeryResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BestBakeryResponseDTO.swift; sourceTree = ""; }; + 0926988A2C3CF94C00A9349D /* BestEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BestEndpoint.swift; sourceTree = ""; }; + 0926988E2C3CF96100A9349D /* BestRepositoryImpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BestRepositoryImpl.swift; sourceTree = ""; }; + 092698922C3CF98B00A9349D /* HomeUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeUseCase.swift; sourceTree = ""; }; + 092698942C3CFD3800A9349D /* BestRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BestRepository.swift; sourceTree = ""; }; 092EFCA32A6195D900E7C262 /* CommonTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTextView.swift; sourceTree = ""; }; 0930D25A2A928B8000A75C7E /* CertificationMarkResponseType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificationMarkResponseType.swift; sourceTree = ""; }; 0930D25C2A928BF200A75C7E /* NearStationResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearStationResponseDTO.swift; sourceTree = ""; }; @@ -372,6 +419,7 @@ 09C6264D2A5B29F8002C8110 /* SearchEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchEnum.swift; sourceTree = ""; }; 09C626552A5B3572002C8110 /* HomeBestReviewResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeBestReviewResponseDTO.swift; sourceTree = ""; }; 09C626572A5B4269002C8110 /* HomeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeHeaderView.swift; sourceTree = ""; }; + 09C8C11D2C3CEFF2009C4213 /* NewHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewHomeViewController.swift; sourceTree = ""; }; 09CA3EF72A5676AA0063897A /* CommonButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonButton.swift; sourceTree = ""; }; 09CA3EFB2A569E4A0063897A /* URLConstant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLConstant.swift; sourceTree = ""; }; 09CD078F2A620D7D00A078DE /* NickNameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NickNameViewController.swift; sourceTree = ""; }; @@ -444,6 +492,7 @@ 3E3DE9E42C25AF7600CA5999 /* ReviewPercentage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewPercentage.swift; sourceTree = ""; }; 3E3DE9E62C25AF8500CA5999 /* Reviews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reviews.swift; sourceTree = ""; }; 3E3DE9E82C25AFA100CA5999 /* Review.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Review.swift; sourceTree = ""; }; + 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GBNetwork.xcodeproj; path = GBNetwork/GBNetwork.xcodeproj; sourceTree = ""; }; 3E452B662A60E68000EA456D /* MyPageResponseDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageResponseDTO.swift; sourceTree = ""; }; 3E452B682A60FF7900EA456D /* MyPageCollectionViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPageCollectionViewFooter.swift; sourceTree = ""; }; 3E452B6A2A614AAD00EA456D /* ImageWithSubtitleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithSubtitleButton.swift; sourceTree = ""; }; @@ -531,7 +580,6 @@ 3EF9F8AD2BBD118700F3E366 /* DummyUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyUseCase.swift; sourceTree = ""; }; 3EF9F8AF2BBD118C00F3E366 /* DummyInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyInterface.swift; sourceTree = ""; }; 3EF9F8B62BBD141600F3E366 /* DummyEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyEndpoint.swift; sourceTree = ""; }; - 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructureDummy.swift; sourceTree = ""; }; 3EFA97852A5EBCA9002E70FA /* LineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineView.swift; sourceTree = ""; }; 3EFA97872A5EBCED002E70FA /* CustomNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; DF483ACB2A652E0100FCD507 /* BookmarkReviewNumberStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkReviewNumberStackView.swift; sourceTree = ""; }; @@ -577,6 +625,7 @@ 090556382A51E16B00752067 /* Then in Frameworks */, 098227EA2AB8B17700872135 /* Sentry in Frameworks */, 0905563B2A51E17800752067 /* SnapKit in Frameworks */, + 3E3DEBE42C31609500CA5999 /* GBNetwork.framework in Frameworks */, 090556432A51E6FC00752067 /* Moya in Frameworks */, 095FB8802AB3427D00C69BD1 /* Amplitude in Frameworks */, 3E36D7D12A8DE65D00B2C1CC /* KakaoSDKUser in Frameworks */, @@ -636,6 +685,14 @@ path = Label; sourceTree = ""; }; + 092698812C3CF2EA00A9349D /* ViewModel */ = { + isa = PBXGroup; + children = ( + 092698822C3CF2F200A9349D /* HomeViewModel.swift */, + ); + path = ViewModel; + sourceTree = ""; + }; 092F11B12A69A6CC00852CA5 /* Cell */ = { isa = PBXGroup; children = ( @@ -978,6 +1035,7 @@ 09E30E812BFEF16F001E107B /* ci_scripts */, 098F32DF2A4200FD0092D09A /* GEON-PPANG-iOS */, 098F32DE2A4200FD0092D09A /* Products */, + 3E3DE9FD2C26981200CA5999 /* Frameworks */, ); sourceTree = ""; }; @@ -997,7 +1055,6 @@ 3EF9F89A2BBD109E00F3E366 /* Domain */, 3EF9F89B2BBD10A000F3E366 /* Data */, 3E8C47CE2BC385A800919E06 /* Core */, - 3E1A4EDD2BCD2343004CA603 /* Infrastructure */, 0961C36B2A501F050031A822 /* Resource */, 0961C3602A501E9F0031A822 /* Global */, ); @@ -1015,6 +1072,7 @@ 09B13F492A593C5900C0C723 /* Home */ = { isa = PBXGroup; children = ( + 092698812C3CF2EA00A9349D /* ViewModel */, 092F11B22A69A6E200852CA5 /* Cell */, 093213FC2A5A74C200875EF6 /* View */, 3E93BCA12BE3744C005B658F /* ViewController */, @@ -1166,14 +1224,6 @@ path = Scene; sourceTree = ""; }; - 3E1A4EDD2BCD2343004CA603 /* Infrastructure */ = { - isa = PBXGroup; - children = ( - 3EF9F8B82BBD17F400F3E366 /* Network */, - ); - path = Infrastructure; - sourceTree = ""; - }; 3E1E73FF2B78AD460082386A /* Model */ = { isa = PBXGroup; children = ( @@ -1322,6 +1372,22 @@ path = BakeryDetail; sourceTree = ""; }; + 3E3DE9FD2C26981200CA5999 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 3E3DEBDC2C31608C00CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */, + 3E3DEBE32C31608C00CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 3E61EE8F2AA9530D004F25DB /* Review */ = { isa = PBXGroup; children = ( @@ -1398,6 +1464,7 @@ 3E8C47CE2BC385A800919E06 /* Core */ = { isa = PBXGroup; children = ( + 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */, 3EF9F8892BBCE9D400F3E366 /* DesignSystem */, ); path = Core; @@ -1422,6 +1489,7 @@ 3E8C47D82BC3B54700919E06 /* Endpoints */ = { isa = PBXGroup; children = ( + 0926988A2C3CF94C00A9349D /* BestEndpoint.swift */, 3EF9F8B62BBD141600F3E366 /* DummyEndpoint.swift */, ); path = Endpoints; @@ -1560,6 +1628,7 @@ isa = PBXGroup; children = ( 09B13F4B2A593C6F00C0C723 /* HomeViewController.swift */, + 09C8C11D2C3CEFF2009C4213 /* NewHomeViewController.swift */, ); path = ViewController; sourceTree = ""; @@ -1845,6 +1914,7 @@ 3EF9F89C2BBD10AC00F3E366 /* UseCase */ = { isa = PBXGroup; children = ( + 092698922C3CF98B00A9349D /* HomeUseCase.swift */, 3EF9F8AD2BBD118700F3E366 /* DummyUseCase.swift */, ); path = UseCase; @@ -1854,6 +1924,7 @@ isa = PBXGroup; children = ( 3EF9F8AF2BBD118C00F3E366 /* DummyInterface.swift */, + 092698942C3CFD3800A9349D /* BestRepository.swift */, ); path = Interface; sourceTree = ""; @@ -1886,6 +1957,7 @@ 3EF9F8A02BBD10D200F3E366 /* Repository */ = { isa = PBXGroup; children = ( + 0926988E2C3CF96100A9349D /* BestRepositoryImpl.swift */, 3EF9F8A92BBD117400F3E366 /* DummyRepository.swift */, ); path = Repository; @@ -1911,6 +1983,8 @@ 3EF9F8A32BBD115800F3E366 /* ResponseDTO */ = { isa = PBXGroup; children = ( + 092698872C3CF93F00A9349D /* BestBakeryResponseDTO.swift */, + 092698862C3CF93F00A9349D /* BestReviewResponseDTO.swift */, 3EF9F8A72BBD116F00F3E366 /* DummyResDTO.swift */, ); path = ResponseDTO; @@ -1933,14 +2007,6 @@ path = Network; sourceTree = ""; }; - 3EF9F8B82BBD17F400F3E366 /* Network */ = { - isa = PBXGroup; - children = ( - 3EF9F8BA2BBD228C00F3E366 /* InfrastructureDummy.swift */, - ); - path = Network; - sourceTree = ""; - }; DF697C082A686ABC008CE4CF /* Cell */ = { isa = PBXGroup; children = ( @@ -2049,6 +2115,7 @@ isa = PBXNativeTarget; buildConfigurationList = 098F32F12A4200FE0092D09A /* Build configuration list for PBXNativeTarget "GEON-PPANG-iOS" */; buildPhases = ( + 3E3DEA002C26981200CA5999 /* Embed Frameworks */, 098F32D92A4200FD0092D09A /* Sources */, 098F32DA2A4200FD0092D09A /* Frameworks */, 098F32DB2A4200FD0092D09A /* Resources */, @@ -2109,6 +2176,12 @@ ); productRefGroup = 098F32DE2A4200FD0092D09A /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 3E3DEBDC2C31608C00CA5999 /* Products */; + ProjectRef = 3E3DEBDB2C31608C00CA5999 /* GBNetwork.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 098F32DC2A4200FD0092D09A /* GEON-PPANG-iOS */, @@ -2116,6 +2189,23 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 3E3DEBE12C31608C00CA5999 /* GBNetwork.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = GBNetwork.framework; + remoteRef = 3E3DEBE02C31608C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 3E3DEBE32C31608C00CA5999 /* GBNetworkTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = GBNetworkTests.xctest; + remoteRef = 3E3DEBE22C31608C00CA5999 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 098F32DB2A4200FD0092D09A /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -2229,6 +2319,7 @@ 09B71C022A59D99200076AC2 /* SearchTextField.swift in Sources */, 093EFA592A61F62D003228CD /* SignInViewController.swift in Sources */, 09B13F482A5931DC00C0C723 /* TabBarController.swift in Sources */, + 092698832C3CF2F200A9349D /* HomeViewModel.swift in Sources */, 3E2EEF752A5C93010093BCA9 /* BottomView.swift in Sources */, 3EA69B382B557954008AE23B /* BakeriesAPI.swift in Sources */, 0961C3642A501EBF0031A822 /* Strings.swift in Sources */, @@ -2254,7 +2345,9 @@ 3E7B21C42A621A9A00C8F8B4 /* SortBakeryCollectionViewCell.swift in Sources */, DFB587BB2A5D588500704B6C /* DrawDashLineView.swift in Sources */, 090556222A51DB3300752067 /* UIFont+.swift in Sources */, + 092698892C3CF93F00A9349D /* BestBakeryResponseDTO.swift in Sources */, 09CA3EFC2A569E4A0063897A /* URLConstant.swift in Sources */, + 092698882C3CF93F00A9349D /* BestReviewResponseDTO.swift in Sources */, 3EA69B652B557A7A008AE23B /* MemberService.swift in Sources */, 0959F1502A65840F00E77CAF /* NetworkBase.swift in Sources */, 3EE343142A6440EB0010C187 /* UICollectionViewCell+.swift in Sources */, @@ -2287,6 +2380,7 @@ DF697C052A671A7B008CE4CF /* BakeryDetailCollectionViewFooter.swift in Sources */, 3EF9F8AA2BBD117400F3E366 /* DummyRepository.swift in Sources */, 097682DA2A5C829D0008F4FB /* GradientImageView.swift in Sources */, + 0926988F2C3CF96100A9349D /* BestRepositoryImpl.swift in Sources */, 097716EB2AA57713001EE6D5 /* LayoutUtils.swift in Sources */, DF697C032A671A6D008CE4CF /* BakeryDetailCollectionViewHeader.swift in Sources */, DFB585FB2A5F565F0077D272 /* BreadTypeStackView.swift in Sources */, @@ -2298,6 +2392,7 @@ 3E3DE9E32C25AF5E00CA5999 /* BakeryFigure.swift in Sources */, 3E8C47F72BC3CA0100919E06 /* MyPageCoordinator.swift in Sources */, 3EFA97862A5EBCA9002E70FA /* LineView.swift in Sources */, + 092698952C3CFD3800A9349D /* BestRepository.swift in Sources */, 3E3543302AAC700600BD926A /* SignUpRequestDTO.swift in Sources */, 3E8C47EF2BC3C9EA00919E06 /* MainCoordinator.swift in Sources */, 0987288D2A5BA1F000A29402 /* BookmarkButton.swift in Sources */, @@ -2327,6 +2422,7 @@ 093214022A5AE27800875EF6 /* Utils.swift in Sources */, 3E8B30002A67A614001BD057 /* BreadRequestType.swift in Sources */, 090556452A51E79B00752067 /* UITextField+.swift in Sources */, + 09C8C11E2C3CEFF2009C4213 /* NewHomeViewController.swift in Sources */, 3E3DE9AD2C25AC6100CA5999 /* Certifications.swift in Sources */, 0959F14E2A65840300E77CAF /* NetworkResult.swift in Sources */, 0959F16C2A658C9500E77CAF /* AuthResponseDTO.swift in Sources */, @@ -2355,8 +2451,10 @@ 3E3DE9D22C25AE6A00CA5999 /* BestReview.swift in Sources */, 3EA69B3E2B557991008AE23B /* MemberAPI.swift in Sources */, 3EB798212AB87188004EC35D /* SetNicknameResponseDTO.swift in Sources */, + 0926988B2C3CF94C00A9349D /* BestEndpoint.swift in Sources */, 090556472A51E7D900752067 /* UITextView+.swift in Sources */, 3EA69B422B5579A7008AE23B /* ReportAPI.swift in Sources */, + 092698932C3CF98B00A9349D /* HomeUseCase.swift in Sources */, 3EDC05D02A5E4FF900EAD950 /* String+.swift in Sources */, 09FD47E42A5E82BB002020BD /* BottomSheetAppearView.swift in Sources */, 3EB798102AB2F448004EC35D /* HeaderEnum.swift in Sources */, @@ -2364,7 +2462,6 @@ 3EB798182AB7D42B004EC35D /* DeleteUserResponseDTO.swift in Sources */, 0905562B2A51DBCE00752067 /* UIStackView+.swift in Sources */, 3E8C47F52BC3C9FC00919E06 /* BakeryListCoordinator.swift in Sources */, - 3EF9F8BB2BBD228C00F3E366 /* InfrastructureDummy.swift in Sources */, 09B13F562A59410C00C0C723 /* CALayer+.swift in Sources */, 09CD07902A620D7D00A078DE /* NickNameViewController.swift in Sources */, DFB1343D2A6284BB00BAB52E /* ReviewProgressView.swift in Sources */, @@ -2444,6 +2541,7 @@ /* Begin XCBuildConfiguration section */ 098F32EF2A4200FE0092D09A /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 09E30E892BFF123C001E107B /* Config.xcconfig */; buildSettings = { ACCESS_TOKEN = "${ACCESS_TOKEN}"; ALWAYS_SEARCH_USER_PATHS = NO; @@ -2506,6 +2604,7 @@ }; 098F32F02A4200FE0092D09A /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 09E30E892BFF123C001E107B /* Config.xcconfig */; buildSettings = { ACCESS_TOKEN = "${ACCESS_TOKEN}"; ALWAYS_SEARCH_USER_PATHS = NO; diff --git a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 1b2650ff..6355ebd2 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/GEON-PPANG-iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,12 @@ { - "originHash" : "a32b0a1c0ad6f6a91a39529043231e700bfb3a573e73a0172a5e40c9106b8bba", "pins" : [ { "identity" : "alamofire", "kind" : "remoteSourceControl", "location" : "https://github.com/Alamofire/Alamofire.git", "state" : { - "revision" : "3dc6a42c7727c49bf26508e29b0a0b35f9c7e1ad", - "version" : "5.8.1" + "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", + "version" : "5.9.1" } }, { @@ -16,7 +15,7 @@ "location" : "https://github.com/amplitude/Amplitude-iOS", "state" : { "branch" : "main", - "revision" : "82fc62448292c13fa0a6b0b11c4524df83fd3f3b" + "revision" : "bfdec453a31fd35942a619ef472fcf2f09e2313a" } }, { @@ -33,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kakao/kakao-ios-sdk", "state" : { - "revision" : "ae3c60cbd4e3b348775f8c766e5b908fa1e66c5a", - "version" : "2.20.0" + "revision" : "e9e649d3ba823c3673867d3d09010fc77005a940", + "version" : "2.22.3" } }, { @@ -42,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/onevcat/Kingfisher.git", "state" : { - "revision" : "5b92f029fab2cce44386d28588098b5be0824ef5", - "version" : "7.11.0" + "revision" : "2ef543ee21d63734e1c004ad6c870255e8716c50", + "version" : "7.12.0" } }, { @@ -69,8 +68,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/ReactiveX/RxSwift.git", "state" : { - "revision" : "9dcaa4b333db437b0fbfaf453fad29069044a8b4", - "version" : "6.6.0" + "revision" : "b06a8c8596e4c3e8e7788e08e720e3248563ce6a", + "version" : "6.7.1" } }, { @@ -78,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "b847a202a517a90763e8fd0656d8028aeee7b78d", - "version" : "8.20.0" + "revision" : "8fd4e804f2e72e0b9c1b189ce4e8349c4d10b6a2", + "version" : "8.30.0" } }, { @@ -87,8 +86,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SnapKit/SnapKit", "state" : { - "revision" : "e74fe2a978d1216c3602b129447c7301573cc2d8", - "version" : "5.7.0" + "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4", + "version" : "5.7.1" } }, { @@ -101,5 +100,5 @@ } } ], - "version" : 3 + "version" : 2 } diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj new file mode 100644 index 00000000..0e332b8a --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 3E3DEB382C3117A400CA5999 /* GBNetwork.docc in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */; }; + 3E3DEB3E2C3117A400CA5999 /* GBNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */; }; + 3E3DEB432C3117A400CA5999 /* GBNetworkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */; }; + 3E3DEB442C3117A400CA5999 /* GBNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E3DEB362C3117A300CA5999 /* GBNetwork.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3E3DEB562C3117F600CA5999 /* GBNetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */; }; + 3E3DEB572C3117F600CA5999 /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */; }; + 3E3DEB582C3117F600CA5999 /* URLRequest+Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */; }; + 3E3DEB592C3117F600CA5999 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB502C3117F600CA5999 /* Response.swift */; }; + 3E3DEB5B2C3117F600CA5999 /* RequestType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB522C3117F600CA5999 /* RequestType.swift */; }; + 3E3DEB5C2C3117F600CA5999 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */; }; + 3E3DEB5D2C3117F600CA5999 /* HTTPTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */; }; + 3E3DEB5E2C3117F600CA5999 /* HTTPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */; }; + 3E3DEB9C2C315DE000CA5999 /* RawResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3E3DEB3F2C3117A400CA5999 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E3DEB2A2C3117A300CA5999 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E3DEB322C3117A300CA5999; + remoteInfo = GBNetwork; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GBNetwork.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E3DEB362C3117A300CA5999 /* GBNetwork.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GBNetwork.h; sourceTree = ""; }; + 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = GBNetwork.docc; sourceTree = ""; }; + 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GBNetworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GBNetworkTests.swift; sourceTree = ""; }; + 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GBNetworkError.swift; sourceTree = ""; }; + 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIClient.swift; sourceTree = ""; }; + 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URLRequest+Encoding.swift"; sourceTree = ""; }; + 3E3DEB502C3117F600CA5999 /* Response.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; + 3E3DEB522C3117F600CA5999 /* RequestType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestType.swift; sourceTree = ""; }; + 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; + 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPTask.swift; sourceTree = ""; }; + 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPHeader.swift; sourceTree = ""; }; + 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RawResponse.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3E3DEB302C3117A300CA5999 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB3A2C3117A400CA5999 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB3E2C3117A400CA5999 /* GBNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3E3DEB292C3117A300CA5999 = { + isa = PBXGroup; + children = ( + 3E3DEB352C3117A300CA5999 /* GBNetwork */, + 3E3DEB412C3117A400CA5999 /* GBNetworkTests */, + 3E3DEB342C3117A300CA5999 /* Products */, + ); + sourceTree = ""; + }; + 3E3DEB342C3117A300CA5999 /* Products */ = { + isa = PBXGroup; + children = ( + 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */, + 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 3E3DEB352C3117A300CA5999 /* GBNetwork */ = { + isa = PBXGroup; + children = ( + 3E3DEB362C3117A300CA5999 /* GBNetwork.h */, + 3E3DEB4E2C3117F500CA5999 /* APIClient.swift */, + 3E3DEB4D2C3117F500CA5999 /* GBNetworkError.swift */, + 3E3DEB552C3117F600CA5999 /* HTTPHeader.swift */, + 3E3DEB532C3117F600CA5999 /* HTTPMethod.swift */, + 3E3DEB542C3117F600CA5999 /* HTTPTask.swift */, + 3E3DEB522C3117F600CA5999 /* RequestType.swift */, + 3E3DEB9B2C315DE000CA5999 /* RawResponse.swift */, + 3E3DEB502C3117F600CA5999 /* Response.swift */, + 3E3DEB4F2C3117F600CA5999 /* URLRequest+Encoding.swift */, + 3E3DEB372C3117A400CA5999 /* GBNetwork.docc */, + ); + path = GBNetwork; + sourceTree = ""; + }; + 3E3DEB412C3117A400CA5999 /* GBNetworkTests */ = { + isa = PBXGroup; + children = ( + 3E3DEB422C3117A400CA5999 /* GBNetworkTests.swift */, + ); + path = GBNetworkTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3E3DEB2E2C3117A300CA5999 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB442C3117A400CA5999 /* GBNetwork.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3E3DEB322C3117A300CA5999 /* GBNetwork */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E3DEB472C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetwork" */; + buildPhases = ( + 3E3DEB2E2C3117A300CA5999 /* Headers */, + 3E3DEB2F2C3117A300CA5999 /* Sources */, + 3E3DEB302C3117A300CA5999 /* Frameworks */, + 3E3DEB312C3117A300CA5999 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GBNetwork; + productName = GBNetwork; + productReference = 3E3DEB332C3117A300CA5999 /* GBNetwork.framework */; + productType = "com.apple.product-type.framework"; + }; + 3E3DEB3C2C3117A400CA5999 /* GBNetworkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E3DEB4A2C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetworkTests" */; + buildPhases = ( + 3E3DEB392C3117A400CA5999 /* Sources */, + 3E3DEB3A2C3117A400CA5999 /* Frameworks */, + 3E3DEB3B2C3117A400CA5999 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3E3DEB402C3117A400CA5999 /* PBXTargetDependency */, + ); + name = GBNetworkTests; + productName = GBNetworkTests; + productReference = 3E3DEB3D2C3117A400CA5999 /* GBNetworkTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3E3DEB2A2C3117A300CA5999 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 3E3DEB322C3117A300CA5999 = { + CreatedOnToolsVersion = 15.4; + }; + 3E3DEB3C2C3117A400CA5999 = { + CreatedOnToolsVersion = 15.4; + }; + }; + }; + buildConfigurationList = 3E3DEB2D2C3117A300CA5999 /* Build configuration list for PBXProject "GBNetwork" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3E3DEB292C3117A300CA5999; + productRefGroup = 3E3DEB342C3117A300CA5999 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3E3DEB322C3117A300CA5999 /* GBNetwork */, + 3E3DEB3C2C3117A400CA5999 /* GBNetworkTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3E3DEB312C3117A300CA5999 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB3B2C3117A400CA5999 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3E3DEB2F2C3117A300CA5999 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB5E2C3117F600CA5999 /* HTTPHeader.swift in Sources */, + 3E3DEB562C3117F600CA5999 /* GBNetworkError.swift in Sources */, + 3E3DEB382C3117A400CA5999 /* GBNetwork.docc in Sources */, + 3E3DEB9C2C315DE000CA5999 /* RawResponse.swift in Sources */, + 3E3DEB5C2C3117F600CA5999 /* HTTPMethod.swift in Sources */, + 3E3DEB582C3117F600CA5999 /* URLRequest+Encoding.swift in Sources */, + 3E3DEB5D2C3117F600CA5999 /* HTTPTask.swift in Sources */, + 3E3DEB572C3117F600CA5999 /* APIClient.swift in Sources */, + 3E3DEB592C3117F600CA5999 /* Response.swift in Sources */, + 3E3DEB5B2C3117F600CA5999 /* RequestType.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E3DEB392C3117A400CA5999 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E3DEB432C3117A400CA5999 /* GBNetworkTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3E3DEB402C3117A400CA5999 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E3DEB322C3117A300CA5999 /* GBNetwork */; + targetProxy = 3E3DEB3F2C3117A400CA5999 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 3E3DEB452C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 3E3DEB462C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3E3DEB482C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = S9G6YGQ76H; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetwork"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3E3DEB492C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = S9G6YGQ76H; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetwork"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 3E3DEB4B2C3117A400CA5999 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S9G6YGQ76H; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetworkTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3E3DEB4C2C3117A400CA5999 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S9G6YGQ76H; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com-id.GBNetworkTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3E3DEB2D2C3117A300CA5999 /* Build configuration list for PBXProject "GBNetwork" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB452C3117A400CA5999 /* Debug */, + 3E3DEB462C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3E3DEB472C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetwork" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB482C3117A400CA5999 /* Debug */, + 3E3DEB492C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3E3DEB4A2C3117A400CA5999 /* Build configuration list for PBXNativeTarget "GBNetworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E3DEB4B2C3117A400CA5999 /* Debug */, + 3E3DEB4C2C3117A400CA5999 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3E3DEB2A2C3117A300CA5999 /* Project object */; +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift new file mode 100644 index 00000000..402fd33f --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/APIClient.swift @@ -0,0 +1,37 @@ +// +// APIClient.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public final class APIClient { + + public init() {} + + public func send( + _ request: Request + ) async throws -> RawResponse { + let configuration = URLSessionConfiguration.default + let session = URLSession(configuration: configuration) + + let (data, urlResponse) = try await session.data(for: request.toURLRequest()) + + guard let httpResponse = urlResponse as? HTTPURLResponse else { + throw GBNetworkError.decodingFailure(.httpDecodingError) + } + + switch httpResponse.statusCode { + case 200..<300: + return .init(data: data, httpResponse: httpResponse) + case 400..<500: + throw GBNetworkError.responseFailure(.clientError(httpResponse)) + case 500..<600: + throw GBNetworkError.responseFailure(.serverError(httpResponse)) + default: + throw GBNetworkError.responseFailure(.invalidError(httpResponse)) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md new file mode 100755 index 00000000..c81ecc33 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.docc/GBNetwork.md @@ -0,0 +1,13 @@ +# ``GBNetwork`` + +Summary + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` \ No newline at end of file diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h new file mode 100644 index 00000000..d8191aaa --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetwork.h @@ -0,0 +1,18 @@ +// +// GBNetwork.h +// GBNetwork +// +// Created by 이성민 on 6/30/24. +// + +#import + +//! Project version number for GBNetwork. +FOUNDATION_EXPORT double GBNetworkVersionNumber; + +//! Project version string for GBNetwork. +FOUNDATION_EXPORT const unsigned char GBNetworkVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift new file mode 100644 index 00000000..22d83625 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/GBNetworkError.swift @@ -0,0 +1,52 @@ +// +// GBNetworkError.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum GBNetworkError: Error { + + // MARK: - Request related errors + + /// Creating `URL` from `String` failure + case urlCreationFailure(urlString: String) + + /// Encoding to `URLRequest` failure + case requestEncodingFailure(EncodingFailureReason) + + // MARK: - Response related errors + + /// Failure received from response + case responseFailure(ResponseFailureReason) + + /// Decoding `Data` to response type failure + case decodingFailure(DecodingFailureReason) + + /// Failure other than the failures above + case unknownFailure(description: String) +} + + +public extension GBNetworkError { + + enum EncodingFailureReason { + case pathError(String) + case jsonError(String) + } + + /// detailed reason why `.responseFailure` occurred + enum ResponseFailureReason { + case clientError(HTTPURLResponse) + case serverError(HTTPURLResponse) + case invalidError(HTTPURLResponse) + } + + enum DecodingFailureReason { + case httpDecodingError + case dtoDecodingError + } +} + diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift new file mode 100644 index 00000000..7131816f --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPHeader.swift @@ -0,0 +1,49 @@ +// +// HTTPHeader.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public struct HTTPHeader { + private(set) var headers: [HTTPHeaderField] = [] + + public init(headers: [HTTPHeaderField]) { + self.headers = headers + } +} + +extension HTTPHeader { + var fields: [String: String] { + .init(uniqueKeysWithValues: headers.map { ($0.key, $0.value) }) + } +} + +public struct HTTPHeaderField { + let key: String + let value: String +} + +public extension HTTPHeaderField { + static func contentType(value: String) -> HTTPHeaderField { + .init(key: "Content-Type", value: value) + } + + static func accessToken(value: String) -> HTTPHeaderField { + .init(key: "Authorization", value: "Bearer \(value)") + } + + static func refreshToken(value: String) -> HTTPHeaderField { + .init(key: "Authorization-refresh", value: "Bearer \(value)") + } + + static func appleRefreshToken(value: String) -> HTTPHeaderField { + .init(key: "Apple-refresh", value: value) + } + + static func platformToken(value: String) -> HTTPHeaderField { + .init(key: "Platform-Token", value: value) + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift new file mode 100644 index 00000000..2b707d9b --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPMethod.swift @@ -0,0 +1,17 @@ +// +// HTTPMethod.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum HTTPMethod: String { + /// HTTP `GET` method + case GET + /// HTTP `POST` method + case POST + /// HTTP `DELETE` method + case DELETE +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift new file mode 100644 index 00000000..b1119856 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/HTTPTask.swift @@ -0,0 +1,17 @@ +// +// HTTPTask.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public enum HTTPTask { + /// plain request + case requestPlain + /// request with query parameters + case requestQuery(_ query: [String: Any]) + /// request with encodable body + case requestEncodable(_ body: Encodable) +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift new file mode 100644 index 00000000..dd0b1aa9 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RawResponse.swift @@ -0,0 +1,28 @@ +// +// RawResponse.swift +// GBNetwork +// +// Created by 이성민 on 6/30/24. +// + +import Foundation + +public struct RawResponse { + public let data: Data + public let httpResponse: HTTPURLResponse + + init(data: Data, httpResponse: HTTPURLResponse) { + self.data = data + self.httpResponse = httpResponse + } +} + +extension RawResponse { + public func decode(to type: DTO.Type) throws -> Response { + do { + return try JSONDecoder().decode(Response.self, from: self.data) + } catch { + throw GBNetworkError.decodingFailure(.dtoDecodingError) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift new file mode 100644 index 00000000..c069831a --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/RequestType.swift @@ -0,0 +1,57 @@ +// +// RequestType.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public protocol RequestType { + + /// Request를 보내는 Base URL + var baseURL: String { get } + + /// Base URL 뒤에 붙는 URL Path + var path: String { get } + + /// 실제로 사용하는 HTTP Method만 정의 - Get, Post, Delete + /// + /// - Request의 HTTP Method: + /// 현재는 GET, POST, DELETE만 사용하기 때문에 세 가지만 설정 + /// + /// - computed property로 한 이유는 encodable에 걸리지 않기 때문 + var method: HTTPMethod { get } + + /// 어떤 방식으로 Request를 보낼지에 대한 정보 + /// + /// - `.requestPlain` - 추가적인 body 또는 query 없이 요청 + /// - `.requestQuery(_ [String: Any])` - url path 뒤에 query 추가하여 요청 + /// - `.requestEncodable(_ : Encodable)` - encodable 한 body와 함께 요청 + var task: HTTPTask { get } + + /// Request 마다 필요한 Header Fields + var headers: HTTPHeader { get } +} + +extension RequestType { + + func toURLRequest() throws -> URLRequest { + guard let url = URL(string: baseURL + path) else { + throw URLError(.badURL) + } + + var urlRequest = URLRequest(url: url) + urlRequest.httpMethod = self.method.rawValue + urlRequest.allHTTPHeaderFields = self.headers.fields + + switch task { + case .requestPlain: + return urlRequest + case let .requestQuery(queries): + return try urlRequest.encode(queries: queries) + case let .requestEncodable(body): + return try urlRequest.encode(body: body) + } + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift new file mode 100644 index 00000000..1db359d1 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/Response.swift @@ -0,0 +1,14 @@ +// +// ResponseType.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +public struct Response: Decodable { + public let code: Int + public let message: String + public let data: DTO +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift new file mode 100644 index 00000000..d51c16be --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetwork/URLRequest+Encoding.swift @@ -0,0 +1,40 @@ +// +// URLRequest+Encoding.swift +// GBNetwork +// +// Created by 이성민 on 6/29/24. +// + +import Foundation + +extension URLRequest { + func encode(queries: [String: Any]) throws -> URLRequest { + guard let url = self.url else { + throw GBNetworkError.requestEncodingFailure(.pathError("missing url")) + } + + var components = URLComponents(string: url.absoluteString) + components?.queryItems = queries.map(toQueryItem) + + guard let encodedURL = components?.url else { + throw GBNetworkError.requestEncodingFailure(.pathError("query encoding fail")) + } + return .init(url: encodedURL) + } + + func encode(body: Encodable) throws -> URLRequest { + do { + var request = self + request.httpBody = try JSONEncoder().encode(body) + return request + } catch { + throw GBNetworkError.requestEncodingFailure(.jsonError("incorrect body type")) + } + } +} + +private extension URLRequest { + func toQueryItem(_ query: (key: String, value: Any)) -> URLQueryItem { + .init(name: query.key, value: query.value as? String) + } +} diff --git a/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift b/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift new file mode 100644 index 00000000..200e9da3 --- /dev/null +++ b/GEON-PPANG-iOS/Core/GBNetwork/GBNetworkTests/GBNetworkTests.swift @@ -0,0 +1,36 @@ +// +// GBNetworkTests.swift +// GBNetworkTests +// +// Created by 이성민 on 6/30/24. +// + +import XCTest +@testable import GBNetwork + +final class GBNetworkTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift b/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift deleted file mode 100644 index 33f4c75d..00000000 --- a/GEON-PPANG-iOS/Infrastructure/Network/InfrastructureDummy.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Endpoint.swift -// GEON-PPANG-iOS -// -// Created by 이성민 on 4/3/24. -// - -import Foundation - -/// `Domain 레이어를 모르면서` Data 레이어에서 신경쓰지 않아도 될 요소들 구현 -/// -/// e.g. -/// - APIClient: API 통신하는 실질적인 부분, request 등과 같은 것들 구현하면 좋을듯 -/// - 외부 DB랑 내부 DB랑 따로 구분해야 할수도 -/// - APIConfiguration도 여기서 정의해두는게 좋을듯, header 등 -/// - Endpoint: 실질적인 `요청을 보내는` 형태 -/// - 그 외에도 현재 `Global/Network/Base`에 있는 몇가지 요소들 등 여기에 구현 From e51fb6a3906859d95fdd60063ac19a54527e91b4 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Wed, 10 Jul 2024 21:00:08 +0900 Subject: [PATCH 17/31] =?UTF-8?q?[Fix]=20#275=20-=20UI=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/StackView/RegionStackView.swift | 2 +- .../Home/HomeBottomCollectionViewCell.swift | 25 ++++----- .../Scene/Home/Home/View/HomeHeaderView.swift | 1 - .../Scene/Home/Home/View/HomeTopView.swift | 53 +++++++++---------- 4 files changed, 36 insertions(+), 45 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift b/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift index d5ed3016..40aed7be 100644 --- a/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift +++ b/GEON-PPANG-iOS/Presentation/Common/StackView/RegionStackView.swift @@ -69,7 +69,7 @@ final class RegionStackView: UIStackView { regionFirstTag.text = data.firstRegion regionSecondTag.text = data.secondRegion - setUI(((data.secondRegion?.isEmpty) != nil)) + setUI(data.secondRegion != nil) } func configureChipCornerRadius(_ radius: CGFloat) { diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBottomCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBottomCollectionViewCell.swift index aa72937a..f1777df7 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBottomCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBottomCollectionViewCell.swift @@ -8,21 +8,27 @@ import UIKit import SnapKit -import Then final class HomeBottomCollectionViewCell: UICollectionViewCell { // MARK: - UI Property - private let footerLabel = UILabel() + private let footerLabel: UILabel = { + let label = UILabel() + label.font = .captionM2 + label.textColor = .gbbGray300 + label.textAlignment = .left + label.numberOfLines = 4 + label.setLineHeight(by: 1.37, with: I18N.Home.bottomSectionTitle) + return label + }() - // MARK: - Life Cycle + // MARK: - init override init(frame: CGRect) { super.init(frame: .zero) setLayout() - setUI() } required init?(coder: NSCoder) { @@ -38,15 +44,4 @@ final class HomeBottomCollectionViewCell: UICollectionViewCell { $0.top.directionalHorizontalEdges.equalToSuperview() } } - - private func setUI() { - - footerLabel.do { - $0.textAlignment = .left - $0.numberOfLines = 4 - $0.basic(font: .captionM2!, - color: .gbbGray300!) - $0.setLineHeight(by: 1.37, with: I18N.Home.bottomSectionTitle) - } - } } diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeHeaderView.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeHeaderView.swift index cfc57930..8b1a82f7 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeHeaderView.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeHeaderView.swift @@ -8,7 +8,6 @@ import UIKit import SnapKit -import Then final class HomeHeaderView: UICollectionReusableView { diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeTopView.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeTopView.swift index 26a71fec..737e6eb8 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeTopView.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/View/HomeTopView.swift @@ -8,7 +8,6 @@ import UIKit import SnapKit -import Then final class HomeTopView: UIView { @@ -18,9 +17,30 @@ final class HomeTopView: UIView { // MARK: - UI Property - private let titleLabel = UILabel() - private let searchTextField = SearchTextField() - private lazy var filterButton = UIButton() + private let titleLabel: UILabel = { + let label = UILabel() + label.font = .title1 + label.textColor = .gbbGray700 + label.numberOfLines = 2 + label.textAlignment = .left + return label + }() + + private lazy var searchTextField: SearchTextField = { + let textField = SearchTextField() + textField.configureViewType(.home) + textField.pushToSearchView = { [weak self] in + self?.pushToSearchView?() + } + return textField + }() + + private let filterButton: UIButton = { + let button = UIButton() + button.setImage(.homeFilterButton, for: .normal) + return button + }() + private let lineView = LineView() // MARK: - Life Cycle @@ -29,7 +49,6 @@ final class HomeTopView: UIView { super.init(frame: .zero) setLayout() - setUI() } required init?(coder: NSCoder) { @@ -69,28 +88,7 @@ final class HomeTopView: UIView { $0.directionalHorizontalEdges.equalToSuperview() } } - - private func setUI() { - - titleLabel.do { - $0.numberOfLines = 2 - $0.textAlignment = .left - $0.basic(font: .title1!, - color: .gbbGray700!) - } - - searchTextField.do { - $0.configureViewType(.home) - $0.pushToSearchView = { - self.pushToSearchView?() - } - } - - filterButton.do { - $0.setImage(.homeFilterButton, for: .normal) - } - } - + func configureTitleText(_ title: String) { titleLabel.text = "\(title)님\n건빵에 오신걸 환영해요!" } @@ -102,5 +100,4 @@ final class HomeTopView: UIView { action() }, for: .touchUpInside) } - } From 32aed73af5067d68b7648e4417ff461ae24275c7 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Wed, 10 Jul 2024 21:06:02 +0900 Subject: [PATCH 18/31] =?UTF-8?q?[Fix]=20#275=20-=20Home=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/HomeBakeryCollectionViewCell.swift | 144 +++++------------- .../ViewController/HomeViewController.swift | 4 +- .../NewHomeViewController.swift | 32 ++-- .../Home/Home/ViewModel/HomeViewModel.swift | 11 +- 4 files changed, 70 insertions(+), 121 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift index f7bc3059..0a728ff3 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift @@ -8,28 +8,37 @@ import UIKit import SnapKit -import Then import Kingfisher final class HomeBakeryCollectionViewCell: UICollectionViewCell { // MARK: - UI Property - private let bakeryImage = UIImageView() - private let markStackView = MarkStackView() - // private var markStackView: GBStackView - private let bakeryTitle = UILabel() private let reviewCount = IconWithTextView(.reviews) private let bookmarkCount = IconWithTextView(.bookmark) private let regionStackView = RegionStackView() - - // MARK: - Life Cycle + // private var markStackView: GBStackView? + private let bakeryImage: UIImageView = { + let view = UIImageView() + view.contentMode = .scaleAspectFill + view.clipsToBounds = true + return view + }() + + private let bakeryTitle: UILabel = { + let label = UILabel() + label.numberOfLines = 1 + label.font = .bodyB1 + label.textColor = .gbbGray700 + label.sizeToFit() + return label + }() + + // MARK: - Init override func prepareForReuse() { super.prepareForReuse() - markStackView.getMarkStatus(false, false, false) - markStackView.configureIconImage(.bigHACCPMark, .bigVeganMark, .bigGMOMark) regionStackView.arrangedSubviews.forEach { regionStackView.removeArrangedSubview($0) } @@ -37,7 +46,6 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { override init(frame: CGRect) { super.init(frame: .zero) - setLayout() setUI() } @@ -80,38 +88,13 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { $0.leading.equalTo(bakeryTitle.snp.leading) $0.bottom.equalToSuperview().inset(16) } - - bakeryImage.addSubview(markStackView) - markStackView.snp.makeConstraints { - $0.top.leading.equalToSuperview().offset(10) - $0.size.equalTo(CGSize(width: heightConsideringNotch(68), height: heightConsideringNotch(28))) - } } private func setUI() { - - self.do { - $0.layer.applyShadow(alpha: 0.1, x: 0, y: 0, blur: 10) - $0.contentView.backgroundColor = .white - $0.contentView.makeCornerRound(radius: 5) - $0.contentView.clipsToBounds = true - } - - bakeryImage.do { - $0.contentMode = .scaleAspectFill - $0.clipsToBounds = true - } - -// markStackView.do { -// $0.configureIconImage(.bigHACCPMark, .bigVeganMark, .bigGMOMark) -// } -// - bakeryTitle.do { - $0.numberOfLines = 1 - $0.basic(font: .bodyB1!, color: .gbbGray700!) - $0.sizeToFit() - } - + layer.applyShadow(alpha: 0.1, x: 0, y: 0, blur: 10) + contentView.backgroundColor = .white + contentView.makeCornerRound(radius: 5) + contentView.clipsToBounds = true } // MARK: - Custom Method @@ -125,13 +108,10 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { bookmarkCount.configureHomeCell(count: data.bookmarkCount) reviewCount.configureHomeCell(count: data.reviewCount) - // markStackView = GBStackView(type: .big, data: [data.certifications.isHaccp, -// data.certifications.isVegan, -// data.certifications.isNonGMO -// ]) -// markStackView.getMarkStatus(data.certifications.isHaccp, -// data.certifications.isVegan, -// data.certifications.isNonGMO) + + self.configureStackView(with: data.certifications) + + // cell builder 머지 후 변경 if data.regions.secondRegion == "" { regionStackView.removeSecondRegion() @@ -139,68 +119,18 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { regionStackView.configureRegion(data.regions) } -} - - -enum GBStackType { - case big - case small - - var images: [UIImage]{ - switch self { - case .big: - return [.bigHACCPMark, .bigVeganMark, .bigGMOMark] - case .small: - return [.smallHACCPMark, .smallVeganMark, .smallGMOMark] - } - } - - var size: Int { - switch self { - case .big: - return 28 - case .small: - return 24 - } - } -} - -final class GBStackView: UIStackView { - - init(type: GBStackType, data: [Bool]) { - super.init(frame: .zero) - - setUI() - createCells(type: type, from: data).forEach { view in - self.addArrangedSubview(view) - } - } - - required init(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - private func createCells(type: GBStackType, from data: [Bool]) -> [UIImageView] { - let images = type.images - var imageIndex = 0 + func configureStackView(with certifications: Certifications) { + let data = [certifications.isHaccp, certifications.isVegan, certifications.isNonGMO] - return data.compactMap { isCertified in - defer { imageIndex += 1 } - guard isCertified, imageIndex < images.count else { return nil } - let imageView = UIImageView(image: images[imageIndex]) - imageView.contentMode = .topLeft - imageView.snp.makeConstraints { $0.size.equalTo(type.size) } - return imageView - } - } - - private func setLayout() { - - } - - private func setUI() { - self.axis = .horizontal - self.spacing = -8 +// self.markStackView = GBStackView(type: .big, data: data) +// +// if let markStackView = markStackView { +// bakeryImage.addSubview(markStackView) +// markStackView.snp.makeConstraints { +// $0.top.leading.equalToSuperview().offset(10) +// $0.size.equalTo(CGSize(width: heightConsideringNotch(68), height: heightConsideringNotch(28))) +// } +// } } } - diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift index c5eaad3e..27d4267d 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift @@ -147,11 +147,11 @@ final class HomeViewController: BaseViewController { switch item { case .bakery(let data): let cell: HomeBakeryCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - // cell.configureCellUI(data: data) +// cell.configureCellUI(data: data) return cell case .reviews(let data): let cell: HomeReviewCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - // cell.configureCellUI(data: data) +// cell.configureCellUI(data: data) return cell case .bottom: let cell: HomeBottomCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index f68bda71..8af5eab5 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -34,10 +34,10 @@ final class NewHomeViewController: UIViewController { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout()) collectionView.showsVerticalScrollIndicator = false collectionView.backgroundColor = .gbbBackground1 - collectionView.registerCells(cells: [HomeBakeryCollectionViewCell.self, - HomeReviewCollectionViewCell.self, - HomeBottomCollectionViewCell.self]) - collectionView.register(header: HomeHeaderView.self) + collectionView.register(HomeBakeryCollectionViewCell.self, forCellWithReuseIdentifier: HomeBakeryCollectionViewCell.identifier) + collectionView.register(HomeReviewCollectionViewCell.self, forCellWithReuseIdentifier: HomeReviewCollectionViewCell.identifier) + collectionView.register(HomeBottomCollectionViewCell.self, forCellWithReuseIdentifier: HomeBottomCollectionViewCell.identifier) + collectionView.register(HomeHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeHeaderView.identifier) collectionView.dataSource = self return collectionView }() @@ -108,21 +108,35 @@ final class NewHomeViewController: UIViewController { private func bindOutputToViewModel(_ output: HomeViewModel.Output?) { guard let output else { return } - output.best + output.bakery .receive(on: RunLoop.main) .sink { err in print("error:\(err)") - } receiveValue: { [weak self] bakery, review in + } receiveValue: { [weak self] bakery in dump(bakery) - self?.updateList(bakery: bakery, review: review) + self?.updateBakery(bakery: bakery) + } + .store(in: &self.cancelBag) + + output.review + .receive(on: RunLoop.main) + .sink { err in + print("error:\(err)") + } receiveValue: { [weak self] review in + dump(review) + self?.updateReview(review: review) } .store(in: &self.cancelBag) } - private func updateList(bakery: [BestBakery], review: [BestReview]) { + private func updateBakery(bakery:[BestBakery]) { self.bakeryList = bakery + self.collectionView.reloadSections(IndexSet(integersIn: 0 ..< 1)) + } + + private func updateReview(review: [BestReview]) { self.reviewList = review - self.collectionView.reloadData() + self.collectionView.reloadSections(IndexSet(integersIn: 1 ..< 2)) } } diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift index d103f8d5..ac3c7386 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift @@ -19,7 +19,8 @@ final class HomeViewModel: ViewModelType { } struct Output { - let best: AnyPublisher<([BestBakery], [BestReview]), Error> + let bakery: AnyPublisher<[BestBakery], Error> + let review: AnyPublisher<[BestReview], Error> } // MARK: - Property @@ -68,9 +69,13 @@ final class HomeViewModel: ViewModelType { } .eraseToAnyPublisher() - let best = Publishers.CombineLatest(bakery, review) - return Output(best: best.eraseToAnyPublisher()) +// let best = Publishers.CombineLatest(bakery, review) +// .map { (_, _) -> () in } +// .eraseToAnyPublisher() + + return Output(bakery: bakery, + review: review) } } From 43cc3293de916f46320e46bdd676b7df567b1dd3 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:38:53 +0900 Subject: [PATCH 19/31] =?UTF-8?q?[Feat]=20#275=20-=20viewcontroller=20publ?= =?UTF-8?q?isher=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Combine/UIViewController+Combine.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift diff --git a/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift b/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift new file mode 100644 index 00000000..9d87349c --- /dev/null +++ b/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift @@ -0,0 +1,18 @@ +// +// UIViewController+.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 7/22/24. +// + +import Combine +import UIKit + +extension UIViewController { + var viewDidLoadPublisher: AnyPublisher { + let selector = #selector(UIViewController.viewDidLoad) + return Just(selector) + .map { _ in Void() } + .eraseToAnyPublisher() + } +} From 7ecbd8894170eb9fcb9f42929429afea0ec088f6 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:39:49 +0900 Subject: [PATCH 20/31] =?UTF-8?q?[Del]=20#275=20-=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataMapping/ResponseDTO/BestBakeryResponseDTO.swift | 2 +- GEON-PPANG-iOS/Domain/Interface/BestRepository.swift | 1 + GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift | 6 ++++-- .../Scene/Home/Home/HomeBakeryCollectionViewCell.swift | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift index d0d657e8..2c242286 100644 --- a/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift +++ b/GEON-PPANG-iOS/Data/Network/DataMapping/ResponseDTO/BestBakeryResponseDTO.swift @@ -29,7 +29,7 @@ struct BestBakeryResponseDTO: Decodable { } extension BestBakeryResponseDTO { - + func toDomain() -> BestBakery { let overview: BakeryOverview = .init( id: bakeryID, diff --git a/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift b/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift index 0f8c24bf..892602b3 100644 --- a/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift +++ b/GEON-PPANG-iOS/Domain/Interface/BestRepository.swift @@ -11,3 +11,4 @@ protocol BestRepository { func getBestBakeries() async throws -> [BestBakery] func getBestReviews() async throws -> [BestReview] } + diff --git a/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift index 81a470fe..c610e629 100644 --- a/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift +++ b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift @@ -13,13 +13,15 @@ protocol HomeUseCase { func fetchBestReviews() async throws -> [BestReview] } + final class HomeUseCaseImpl: HomeUseCase { + let bestRepository: BestRepository - init(bestRepository: BestRepository) { + init(bestRepository: BestRepository) { self.bestRepository = bestRepository } - + func fetchBestBakeries() async throws -> [BestBakery] { do { return try await bestRepository.getBestBakeries() diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift index 0a728ff3..ed5a70c1 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeBakeryCollectionViewCell.swift @@ -121,7 +121,6 @@ final class HomeBakeryCollectionViewCell: UICollectionViewCell { } func configureStackView(with certifications: Certifications) { - let data = [certifications.isHaccp, certifications.isVegan, certifications.isNonGMO] // self.markStackView = GBStackView(type: .big, data: data) // From 9060306a12fbac66cefb8402f1ac4d1790f6a643 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:40:23 +0900 Subject: [PATCH 21/31] =?UTF-8?q?[Fix]=20#275=20-=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/Home/ViewModel/HomeViewModel.swift | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift index ac3c7386..51181e1b 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift @@ -5,17 +5,14 @@ // Created by JEONGEUN KIM on 7/9/24. // +import Combine import Foundation -import Combine final class HomeViewModel: ViewModelType { struct Input { - let viewWillAppear: PassthroughSubject - init(viewWillAppear: PassthroughSubject) { - self.viewWillAppear = viewWillAppear - } + let viewDidLoad: AnyPublisher } struct Output { @@ -27,7 +24,7 @@ final class HomeViewModel: ViewModelType { private let usecase: HomeUseCase private var cancellable: Set = Set() - + init(usecase: HomeUseCase) { self.usecase = usecase } @@ -35,7 +32,7 @@ final class HomeViewModel: ViewModelType { // MARK: - func func transform(_ input: Input) -> Output { - let bakery = input.viewWillAppear + let bakery = input.viewDidLoad .compactMap { [weak self] in self } .flatMap { _ -> AnyPublisher<[BestBakery], Error> in Future<[BestBakery], Error> { promise in @@ -52,14 +49,14 @@ final class HomeViewModel: ViewModelType { } .eraseToAnyPublisher() - let review = input.viewWillAppear + let review = input.viewDidLoad .compactMap { [weak self] in self } .flatMap { _ -> AnyPublisher<[BestReview], Error> in return Future<[BestReview], Error> { promise in Task { do { let review = try await self.fetchBestReview() - promise(.success(review)) + promise(.success(review)) } catch { promise(.failure(error)) } @@ -68,14 +65,8 @@ final class HomeViewModel: ViewModelType { .eraseToAnyPublisher() } .eraseToAnyPublisher() - - -// let best = Publishers.CombineLatest(bakery, review) -// .map { (_, _) -> () in } -// .eraseToAnyPublisher() - - return Output(bakery: bakery, - review: review) + + return Output(bakery: bakery, review: review) } } From 044305b234b3bf3585a3bc01d739a3bd4918cd09 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:41:14 +0900 Subject: [PATCH 22/31] =?UTF-8?q?[Fix]=20#275=20-=20review=20cell=20UI=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/HomeReviewCollectionViewCell.swift | 89 +++++++++---------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift index a903831f..b61bf311 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/HomeReviewCollectionViewCell.swift @@ -9,7 +9,6 @@ import UIKit import Kingfisher import SnapKit -import Then final class HomeReviewCollectionViewCell: UICollectionViewCell { @@ -20,21 +19,52 @@ final class HomeReviewCollectionViewCell: UICollectionViewCell { // MARK: - UI Property - private lazy var bakeryImage = GradientImageView(colors: [UIColor.clear.cgColor, UIColor.black.withAlphaComponent(0.5).cgColor]) - private let reviewTitle = UILabel() - private let bakeryTitle = UILabel() + private lazy var bakeryImage: GradientImageView = { + let view = GradientImageView(colors: [UIColor.clear.cgColor, UIColor.black.withAlphaComponent(0.5).cgColor]) + view.contentMode = .scaleAspectFill + view.clipsToBounds = true + return view + }() + + private let reviewTitle: UILabel = { + let label = UILabel() + label.font = .bodyB2 + label.textColor = .gbbWhite + label.textAlignment = .left + label.numberOfLines = 2 + return label + }() + + private let bakeryTitle: UILabel = { + let label = UILabel() + label.font = .bodyB1 + label.textColor = .gbbGray700 + label.textAlignment = .left + label.numberOfLines = 1 + return label + }() + + private lazy var collectionView: UICollectionView = { + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: OptionsCollectionViewFlowLayout()) + collectionView.register(DescriptionCollectionViewCell.self, + forCellWithReuseIdentifier: DescriptionCollectionViewCell.identifier) + collectionView.isScrollEnabled = false + collectionView.backgroundColor = .clear + collectionView.delegate = self + collectionView.dataSource = self + return collectionView + }() + private let reviewCount = IconWithTextView(.reviews) private let bookmarkCount = IconWithTextView(.bookmark) - private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: OptionsCollectionViewFlowLayout()) - // MARK: - Life Cycle + // MARK: - init override init(frame: CGRect) { super.init(frame: .zero) setLayout() setUI() - setRegister() } required init?(coder: NSCoder) { @@ -87,38 +117,10 @@ final class HomeReviewCollectionViewCell: UICollectionViewCell { private func setUI() { - self.do { - $0.layer.applyShadow(alpha: 0.1, x: 0, y: 0, blur: 10) - $0.contentView.backgroundColor = .white - $0.contentView.makeCornerRound(radius: 5) - $0.contentView.clipsToBounds = true - } - - bakeryImage.do { - $0.contentMode = .scaleAspectFill - $0.clipsToBounds = true - } - - reviewTitle.do { - $0.basic(font: .bodyB2!, color: .white) - $0.textAlignment = .left - $0.numberOfLines = 2 - } - - collectionView.do { - $0.isScrollEnabled = false - $0.backgroundColor = .clear - $0.delegate = self - $0.dataSource = self - } - - bakeryTitle.do { - $0.numberOfLines = 1 - $0.basic(font: .bodyB1!, color: .gbbGray700!) - $0.textAlignment = .left - - } - + self.layer.applyShadow(alpha: 0.1, x: 0, y: 0, blur: 10) + self.contentView.backgroundColor = .white + self.contentView.makeCornerRound(radius: 5) + self.contentView.clipsToBounds = true } func configureCellUI(data: BestReview) { @@ -139,15 +141,6 @@ final class HomeReviewCollectionViewCell: UICollectionViewCell { } } -// MARK: - CollectionView Register - -extension HomeReviewCollectionViewCell { - private func setRegister() { - - collectionView.register(cell: DescriptionCollectionViewCell.self) - } -} - // MARK: - UICollectionViewDataSource extension HomeReviewCollectionViewCell: UICollectionViewDataSource { From fd12483a8eb643ba79fd75b6c94c65cd66b9e06e Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:41:47 +0900 Subject: [PATCH 23/31] =?UTF-8?q?[Fix]=20#275=20-=20Home=20UI=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 20 ++ .../NewHomeViewController.swift | 196 ++++++++++++------ 2 files changed, 147 insertions(+), 69 deletions(-) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index cb36662a..986a2272 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -81,6 +81,7 @@ 098716B62A60F52200538D05 /* BakeryTypeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098716B52A60F52200538D05 /* BakeryTypeProtocol.swift */; }; 098716B82A6138BD00538D05 /* MyReviewsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098716B72A6138BD00538D05 /* MyReviewsHeaderView.swift */; }; 0987288D2A5BA1F000A29402 /* BookmarkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0987288C2A5BA1F000A29402 /* BookmarkButton.swift */; }; + 098800A82C4E3A62009E6F43 /* UIViewController+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */; }; 098F32EA2A4200FE0092D09A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 098F32E92A4200FE0092D09A /* Assets.xcassets */; }; 098F32ED2A4200FE0092D09A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 098F32EB2A4200FE0092D09A /* LaunchScreen.storyboard */; }; 09980CFB2A99A9800098550C /* SignInPropertyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09980CFA2A99A9800098550C /* SignInPropertyType.swift */; }; @@ -399,6 +400,7 @@ 098716B52A60F52200538D05 /* BakeryTypeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BakeryTypeProtocol.swift; sourceTree = ""; }; 098716B72A6138BD00538D05 /* MyReviewsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyReviewsHeaderView.swift; sourceTree = ""; }; 0987288C2A5BA1F000A29402 /* BookmarkButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkButton.swift; sourceTree = ""; }; + 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Combine.swift"; sourceTree = ""; }; 098F32DD2A4200FD0092D09A /* GEON-PPANG-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GEON-PPANG-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 098F32E02A4200FD0092D09A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 098F32E22A4200FD0092D09A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -1028,6 +1030,22 @@ path = View; sourceTree = ""; }; + 098800A52C4E3A3B009E6F43 /* Extension */ = { + isa = PBXGroup; + children = ( + 098800A62C4E3A4D009E6F43 /* Combine */, + ); + path = Extension; + sourceTree = ""; + }; + 098800A62C4E3A4D009E6F43 /* Combine */ = { + isa = PBXGroup; + children = ( + 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */, + ); + path = Combine; + sourceTree = ""; + }; 098F32D42A4200FD0092D09A = { isa = PBXGroup; children = ( @@ -1498,6 +1516,7 @@ 3E8C47E02BC3B81B00919E06 /* Utils */ = { isa = PBXGroup; children = ( + 098800A52C4E3A3B009E6F43 /* Extension */, 3E8C47E12BC3B82500919E06 /* DummyUIUtils.swift */, ); path = Utils; @@ -2343,6 +2362,7 @@ 3E3DE9C92C25AE0100CA5999 /* PasswordValidationError.swift in Sources */, 0959F1702A658CA400E77CAF /* HomeBestBakeryResponseDTO.swift in Sources */, 3E7B21C42A621A9A00C8F8B4 /* SortBakeryCollectionViewCell.swift in Sources */, + 098800A82C4E3A62009E6F43 /* UIViewController+Combine.swift in Sources */, DFB587BB2A5D588500704B6C /* DrawDashLineView.swift in Sources */, 090556222A51DB3300752067 /* UIFont+.swift in Sources */, 092698892C3CF93F00A9349D /* BestBakeryResponseDTO.swift in Sources */, diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index 8af5eab5..b74b92d1 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -18,7 +18,7 @@ final class NewHomeViewController: UIViewController { private let viewModel: any ViewModelType private var cancelBag: Set = Set() - private let viewWillAppearPublisher: PassthroughSubject = PassthroughSubject() + private let cellTappedPublisher: PassthroughSubject = PassthroughSubject() private var bakeryList: [BestBakery] = [] private var reviewList: [BestReview] = [] @@ -34,11 +34,15 @@ final class NewHomeViewController: UIViewController { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout()) collectionView.showsVerticalScrollIndicator = false collectionView.backgroundColor = .gbbBackground1 - collectionView.register(HomeBakeryCollectionViewCell.self, forCellWithReuseIdentifier: HomeBakeryCollectionViewCell.identifier) - collectionView.register(HomeReviewCollectionViewCell.self, forCellWithReuseIdentifier: HomeReviewCollectionViewCell.identifier) + collectionView.register(HomeBakeryCollectionViewCell.self, + forCellWithReuseIdentifier: HomeBakeryCollectionViewCell.identifier) + collectionView.register(HomeReviewCollectionViewCell.self, + forCellWithReuseIdentifier: HomeReviewCollectionViewCell.identifier) collectionView.register(HomeBottomCollectionViewCell.self, forCellWithReuseIdentifier: HomeBottomCollectionViewCell.identifier) - collectionView.register(HomeHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeHeaderView.identifier) + collectionView.register(HomeHeaderView.self, + forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeHeaderView.identifier) collectionView.dataSource = self + collectionView.delegate = self return collectionView }() @@ -56,12 +60,6 @@ final class NewHomeViewController: UIViewController { // MARK: - Life cycle - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - viewWillAppearPublisher.send() - } - override func viewDidLoad() { super.viewDidLoad() @@ -99,9 +97,7 @@ final class NewHomeViewController: UIViewController { private func transformedOutput() -> HomeViewModel.Output? { guard let viewModel = self.viewModel as? HomeViewModel else { return nil } - let input = HomeViewModel.Input( - viewWillAppear: self.viewWillAppearPublisher - ) + let input = HomeViewModel.Input(viewDidLoad: self.viewDidLoadPublisher) return viewModel.transform(input) } @@ -113,7 +109,6 @@ final class NewHomeViewController: UIViewController { .sink { err in print("error:\(err)") } receiveValue: { [weak self] bakery in - dump(bakery) self?.updateBakery(bakery: bakery) } .store(in: &self.cancelBag) @@ -123,7 +118,6 @@ final class NewHomeViewController: UIViewController { .sink { err in print("error:\(err)") } receiveValue: { [weak self] review in - dump(review) self?.updateReview(review: review) } .store(in: &self.cancelBag) @@ -131,15 +125,100 @@ final class NewHomeViewController: UIViewController { private func updateBakery(bakery:[BestBakery]) { self.bakeryList = bakery - self.collectionView.reloadSections(IndexSet(integersIn: 0 ..< 1)) + UIView.performWithoutAnimation { + self.collectionView.reloadSections(IndexSet(integer: 0)) + + } } private func updateReview(review: [BestReview]) { self.reviewList = review - self.collectionView.reloadSections(IndexSet(integersIn: 1 ..< 2)) + UIView.performWithoutAnimation { + self.collectionView.reloadSections(IndexSet(integer: 1)) + } } } +// MARK: - CollectionView Layout + +extension NewHomeViewController { + + private func layout() -> UICollectionViewCompositionalLayout { + return UICollectionViewCompositionalLayout(sectionProvider: { [weak self] sectionIndex, _ in + switch sectionIndex { + case 0: + return self?.bestSection(headerSize: 49) + case 1: + return self?.bestSection(headerSize: 25) + default: + return self?.bottomSection() + } + }) + } + + private func bestSection(headerSize: CGFloat) -> NSCollectionLayoutSection { + + let itemGroupSize = NSCollectionLayoutSize( + widthDimension: .absolute(convertByWidthRatio(192)), + heightDimension: .absolute(heightConsideringNotch(236)) + ) + let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) + + let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemGroupSize, subitems: [item]) + + let section = NSCollectionLayoutSection(group: group) + section.interGroupSpacing = 12 + section.orthogonalScrollingBehavior = .continuous + section.boundarySupplementaryItems = bestSectionHeader(to: headerSize) + section.contentInsets = NSDirectionalEdgeInsets(top: 24, + leading: 24, + bottom: 30, + trailing: 24) + + return section + } + + private func bottomSection() -> NSCollectionLayoutSection { + + let itemGroupSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1), + heightDimension: .absolute(72) + ) + let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) + + let group = NSCollectionLayoutGroup.vertical( + layoutSize: itemGroupSize, + subitem: item, + count: 1 + ) + + let section = NSCollectionLayoutSection(group: group) + section.contentInsets = NSDirectionalEdgeInsets(top: 14, + leading: 24, + bottom: 30, + trailing: 24) + + return section + } + + private func bestSectionHeader(to size: CGFloat) -> [NSCollectionLayoutBoundarySupplementaryItem] { + let headerSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1), + heightDimension: .absolute(size) + ) + + let header = NSCollectionLayoutBoundarySupplementaryItem( + layoutSize: headerSize, + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .top + ) + + return [header] + } +} + +// MARK: - CollectionView DataSource + extension NewHomeViewController: UICollectionViewDataSource { func numberOfSections(in collectionView: UICollectionView) -> Int { @@ -187,66 +266,45 @@ extension NewHomeViewController: UICollectionViewDataSource { guard let title = Sections(rawValue: indexPath.section)?.title else { return UICollectionReusableView() } // nickname - header.configureSectionHeaderTitle(nil, title) + header.configureSectionHeaderTitle("nil", title) return header } } -extension NewHomeViewController { - private func layout() -> UICollectionViewCompositionalLayout { - - return UICollectionViewCompositionalLayout(sectionProvider: { [weak self] sectionIndex, _ in - switch sectionIndex { - case 0: - return self?.bestSection(headerSize: 49) - case 1: - return self?.bestSection(headerSize: 25) - default: - return self?.bottomSection() - } - }) - } +// MARK: - CollectionView Delegate + +extension NewHomeViewController: UICollectionViewDelegate { - private func bestSection(headerSize: CGFloat) -> NSCollectionLayoutSection { - - let itemGroupSize = NSCollectionLayoutSize(widthDimension: .absolute(convertByWidthRatio(192)), - heightDimension: .absolute(heightConsideringNotch(236))) - let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) - let group = NSCollectionLayoutGroup.horizontal(layoutSize: itemGroupSize, subitems: [item]) - - let section = NSCollectionLayoutSection(group: group) - section.interGroupSpacing = 12 - section.orthogonalScrollingBehavior = .continuous + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), - heightDimension: .absolute(headerSize)) - let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, - elementKind: UICollectionView.elementKindSectionHeader, - alignment: .top) - section.contentInsets = NSDirectionalEdgeInsets(top: 24, - leading: 24, - bottom: 30, - trailing: 24) + let (id, bakery) = getBakeryData(for: indexPath) - section.boundarySupplementaryItems = [header] - return section + if let id = id, let bakery = bakery { + navigateToDetailViewController(with: id) + logAnalytics(for: bakery) + } } - private func bottomSection() -> NSCollectionLayoutSection { - - let itemGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), - heightDimension: .absolute(72)) - let item = NSCollectionLayoutItem(layoutSize: itemGroupSize) - - let group = NSCollectionLayoutGroup.vertical(layoutSize: itemGroupSize, - subitem: item, - count: 1) - let section = NSCollectionLayoutSection(group: group) - section.contentInsets = NSDirectionalEdgeInsets(top: 14, - leading: 24, - bottom: 30, - trailing: 24) - - return section + private func getBakeryData(for indexPath: IndexPath) -> (Int?, String?) { + switch indexPath.section { + case 0: + return (bakeryList[indexPath.item].overview.id, bakeryList[indexPath.item].overview.name) + case 1: + return (reviewList[indexPath.item].overview.id, reviewList[indexPath.item].overview.name) + default: + return (nil, nil) + } + } + + private func navigateToDetailViewController(with id: Int) { + let nextViewController = BakeryDetailViewController() + nextViewController.bakeryID = id + navigationController?.isNavigationBarHidden = true + navigationController?.pushViewController(nextViewController, animated: true) + } + + private func logAnalytics(for bakery: String) { + AnalyticManager.log(event: .home(.clickRecommendStore(bakery: bakery))) + AnalyticManager.log(event: .detail(.viewDetailpageAt(source: AnalyticEventType.HOME.rawValue))) } } From 8394674c7ede1c25ada7b24e9df3695afbae56a9 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Mon, 22 Jul 2024 17:45:42 +0900 Subject: [PATCH 24/31] =?UTF-8?q?[Del]=20#275=20-=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/Home/ViewController/NewHomeViewController.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index b74b92d1..2f295db0 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -17,9 +17,7 @@ final class NewHomeViewController: UIViewController { private let viewModel: any ViewModelType private var cancelBag: Set = Set() - - private let cellTappedPublisher: PassthroughSubject = PassthroughSubject() - + private var bakeryList: [BestBakery] = [] private var reviewList: [BestReview] = [] From 0ebb64d14883c4bb7bf8e3f6b07f8ac4aef3043d Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 14:54:03 +0900 Subject: [PATCH 25/31] =?UTF-8?q?[Fix]=20#275=20-=20DiffableDataSource?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/Entity/Base/BakeryOverview.swift | 2 +- .../Domain/Entity/Base/Certifications.swift | 2 +- .../Domain/Entity/Base/Regions.swift | 2 +- .../Domain/Entity/Home/BestBakery.swift | 2 +- .../Domain/Entity/Home/BestReview.swift | 2 +- .../NewHomeViewController.swift | 276 ++++++++++++------ .../Home/Home/ViewModel/HomeViewModel.swift | 66 ++--- 7 files changed, 222 insertions(+), 130 deletions(-) diff --git a/GEON-PPANG-iOS/Domain/Entity/Base/BakeryOverview.swift b/GEON-PPANG-iOS/Domain/Entity/Base/BakeryOverview.swift index 6a5bdc50..c6ff7310 100644 --- a/GEON-PPANG-iOS/Domain/Entity/Base/BakeryOverview.swift +++ b/GEON-PPANG-iOS/Domain/Entity/Base/BakeryOverview.swift @@ -7,7 +7,7 @@ import Foundation -struct BakeryOverview { +struct BakeryOverview: Hashable { let id: Int let name: String let image: String diff --git a/GEON-PPANG-iOS/Domain/Entity/Base/Certifications.swift b/GEON-PPANG-iOS/Domain/Entity/Base/Certifications.swift index 9c2cbfac..aa907746 100644 --- a/GEON-PPANG-iOS/Domain/Entity/Base/Certifications.swift +++ b/GEON-PPANG-iOS/Domain/Entity/Base/Certifications.swift @@ -7,7 +7,7 @@ import Foundation -struct Certifications { +struct Certifications: Hashable { let isHaccp: Bool let isVegan: Bool let isNonGMO: Bool diff --git a/GEON-PPANG-iOS/Domain/Entity/Base/Regions.swift b/GEON-PPANG-iOS/Domain/Entity/Base/Regions.swift index 25e349b1..4f64f422 100644 --- a/GEON-PPANG-iOS/Domain/Entity/Base/Regions.swift +++ b/GEON-PPANG-iOS/Domain/Entity/Base/Regions.swift @@ -7,7 +7,7 @@ import Foundation -struct Regions { +struct Regions: Hashable { let firstRegion: String let secondRegion: String? } diff --git a/GEON-PPANG-iOS/Domain/Entity/Home/BestBakery.swift b/GEON-PPANG-iOS/Domain/Entity/Home/BestBakery.swift index fac8d31f..7f7ca489 100644 --- a/GEON-PPANG-iOS/Domain/Entity/Home/BestBakery.swift +++ b/GEON-PPANG-iOS/Domain/Entity/Home/BestBakery.swift @@ -7,7 +7,7 @@ import Foundation -struct BestBakery { +struct BestBakery: Hashable { let overview: BakeryOverview let certifications: Certifications let bookmarkCount: Int diff --git a/GEON-PPANG-iOS/Domain/Entity/Home/BestReview.swift b/GEON-PPANG-iOS/Domain/Entity/Home/BestReview.swift index 0b1a7605..161786bf 100644 --- a/GEON-PPANG-iOS/Domain/Entity/Home/BestReview.swift +++ b/GEON-PPANG-iOS/Domain/Entity/Home/BestReview.swift @@ -7,7 +7,7 @@ import Foundation -struct BestReview { +struct BestReview: Hashable { let overview: BakeryOverview let reviewOverview: String let recommendKeywords: [String] diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index 2f295db0..332b0b90 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -8,21 +8,34 @@ import Combine import UIKit +import SnapKit final class NewHomeViewController: UIViewController { + enum Sections: Int, CaseIterable { + case bakery + case review + case bottom + } + + enum Item: Hashable { + case bakery(BestBakery) + case review(BestReview) + case bottom + } + // MARK: - Property - private lazy var safeArea = self.view.safeAreaLayoutGuide + private var dataSource: UICollectionViewDiffableDataSource? + private var snapShot: NSDiffableDataSourceSnapshot? private let viewModel: any ViewModelType private var cancelBag: Set = Set() - - private var bakeryList: [BestBakery] = [] - private var reviewList: [BestReview] = [] // MARK: - UI Property + private lazy var safeArea = self.view.safeAreaLayoutGuide + private let topView: HomeTopView = { let view = HomeTopView() return view @@ -36,11 +49,11 @@ final class NewHomeViewController: UIViewController { forCellWithReuseIdentifier: HomeBakeryCollectionViewCell.identifier) collectionView.register(HomeReviewCollectionViewCell.self, forCellWithReuseIdentifier: HomeReviewCollectionViewCell.identifier) - collectionView.register(HomeBottomCollectionViewCell.self, forCellWithReuseIdentifier: HomeBottomCollectionViewCell.identifier) + collectionView.register(HomeBottomCollectionViewCell.self, + forCellWithReuseIdentifier: HomeBottomCollectionViewCell.identifier) collectionView.register(HomeHeaderView.self, - forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: HomeHeaderView.identifier) - collectionView.dataSource = self - collectionView.delegate = self + forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, + withReuseIdentifier: HomeHeaderView.identifier) return collectionView }() @@ -64,10 +77,11 @@ final class NewHomeViewController: UIViewController { setLayout() setUI() setViewModel() + setDataSource() + bindCollectionViewEvents() } private func setLayout() { - view.addSubview(topView) topView.snp.makeConstraints { $0.top.equalToSuperview().offset(heightConsideringNotch(44)) @@ -107,7 +121,7 @@ final class NewHomeViewController: UIViewController { .sink { err in print("error:\(err)") } receiveValue: { [weak self] bakery in - self?.updateBakery(bakery: bakery) + self?.reloadBestList(bakery: bakery) } .store(in: &self.cancelBag) @@ -116,25 +130,125 @@ final class NewHomeViewController: UIViewController { .sink { err in print("error:\(err)") } receiveValue: { [weak self] review in - self?.updateReview(review: review) + self?.reloadBestList(review: review) } .store(in: &self.cancelBag) } +} + +extension NewHomeViewController { + + func setDataSource() { + self.dataSource = self.BestCollectionViewDataSource() + self.configureSnapshot() + self.configureSupplementaryView() + } - private func updateBakery(bakery:[BestBakery]) { - self.bakeryList = bakery - UIView.performWithoutAnimation { - self.collectionView.reloadSections(IndexSet(integer: 0)) + func BestCollectionViewDataSource() -> UICollectionViewDiffableDataSource { + let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in + switch item { + case .bakery(let data): + let cell: HomeBakeryCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + cell.configureCellUI(data: data) + return cell + case .review(let data): + let cell: HomeReviewCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + cell.configureCellUI(data: data) + return cell + case .bottom: + let cell: HomeBottomCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) + return cell + } } + + return dataSource } - private func updateReview(review: [BestReview]) { - self.reviewList = review - UIView.performWithoutAnimation { - self.collectionView.reloadSections(IndexSet(integer: 1)) + private func configureSupplementaryView() { + dataSource?.supplementaryViewProvider = { (collectionView, _, indexPath) in + guard let section = Sections(rawValue: indexPath.section) else { fatalError() } + + let header: HomeHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, indexPath: indexPath) + + // header.configureSectionHeaderTitle("", "") + return header + } + } + + func configureSnapshot() { + self.snapShot = NSDiffableDataSourceSnapshot() + snapShot?.appendSections([.bakery,.review,.bottom]) + if let snapShot { + self.dataSource?.apply(snapShot) + } + } + + private func reloadBestList(bakery: [BestBakery] = [], review: [BestReview] = []) { + // 현재 스냅샷을 가져와서 기존의 아이템이 비어있을 때만 update + guard var snapShot = self.dataSource?.snapshot() else { return } + + let previousBakeryData = snapShot.itemIdentifiers(inSection: .bakery) + let previousReviewData = snapShot.itemIdentifiers(inSection: .review) + + if previousBakeryData.isEmpty { + let bakeryItems = bakery.map { Item.bakery($0) } + snapShot.appendItems(bakeryItems, toSection: .bakery) + } + + if previousReviewData.isEmpty { + let reviewItems = review.map { Item.review($0) } + snapShot.appendItems(reviewItems, toSection: .review) + } + + snapShot.appendItems([.bottom], toSection: .bottom) + + self.dataSource?.apply(snapShot, animatingDifferences: false) + } +} + +extension NewHomeViewController { + + private func bindCollectionViewEvents() { + let didSelectPublisher = CollectionViewPublisher(collectionView: collectionView, event: .didSelect) + didSelectPublisher + .sink { [weak self] indexPath in + self?.handleSelection(for: indexPath) + } + .store(in: &cancelBag) + } + + private func handleSelection(for indexPath: IndexPath) { + guard let (id, bakery) = getBakeryData(for: indexPath) else { return } + + self.navigateToDetailViewController(with: id) + self.logAnalytics(for: bakery) + } + + private func getBakeryData(for indexPath: IndexPath) -> (Int, String)? { + guard let item = dataSource?.itemIdentifier(for: indexPath) else { return nil } + + switch item { + case .bakery(let data): + return (data.overview.id, data.overview.name) + case .review(let data): + return (data.overview.id, data.overview.name) + default: + return nil } } + + private func navigateToDetailViewController(with id: Int) { + let nextViewController = BakeryDetailViewController() + nextViewController.bakeryID = id + navigationController?.isNavigationBarHidden = true + navigationController?.pushViewController(nextViewController, animated: true) + } + + private func logAnalytics(for bakery: String) { + AnalyticManager.log(event: .home(.clickRecommendStore(bakery: bakery))) + AnalyticManager.log(event: .detail(.viewDetailpageAt(source: AnalyticEventType.HOME.rawValue))) + } } // MARK: - CollectionView Layout @@ -215,94 +329,76 @@ extension NewHomeViewController { } } -// MARK: - CollectionView DataSource +enum Event { + case didSelect + case didDeselect +} -extension NewHomeViewController: UICollectionViewDataSource { +final class CollectionViewSubscription: Subscription where SubscriberType.Input == IndexPath { + private var subscriber: SubscriberType? + private weak var collectionView: UICollectionView? + private var delegateProxy: CollectionViewDelegateProxy? - func numberOfSections(in collectionView: UICollectionView) -> Int { - return 3 + init(subscriber: SubscriberType, collectionView: UICollectionView, event: Event) { + self.subscriber = subscriber + self.collectionView = collectionView + + let delegateProxy = CollectionViewDelegateProxy( + event: event, + handler: { [weak self] indexPath in + _ = self?.subscriber?.receive(indexPath) + } + ) + + self.delegateProxy = delegateProxy + collectionView.delegate = delegateProxy } - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - switch section { - case 0: - return bakeryList.count - case 1: - return reviewList.count - default: - return 1 - } + func request(_ demand: Subscribers.Demand) { + // 요구 처리 로직 추가 가능 } - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - switch indexPath.section { - case 0: - let cell: HomeBakeryCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - let item = self.bakeryList[indexPath.item] - cell.configureCellUI(data: item) - return cell - case 1: - let cell: HomeReviewCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - let item = self.reviewList[indexPath.item] - cell.configureCellUI(data: item) - return cell - case 2: - let cell: HomeBottomCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath) - return cell - default: - return UICollectionViewCell() - } - } - - func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { - guard kind == UICollectionView.elementKindSectionHeader, - let header = collectionView.dequeueReusableSupplementaryView( - ofKind: kind, - withReuseIdentifier: HomeHeaderView.identifier, - for: indexPath - ) as? HomeHeaderView else { return UICollectionReusableView() } - - guard let title = Sections(rawValue: indexPath.section)?.title else { return UICollectionReusableView() } - // nickname - header.configureSectionHeaderTitle("nil", title) - return header + func cancel() { + subscriber = nil + delegateProxy = nil } } -// MARK: - CollectionView Delegate - -extension NewHomeViewController: UICollectionViewDelegate { +private class CollectionViewDelegateProxy: NSObject, UICollectionViewDelegate { + private let event: Event + private let handler: (IndexPath) -> Void + + init(event: Event, handler: @escaping (IndexPath) -> Void) { + self.event = event + self.handler = handler + } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - - let (id, bakery) = getBakeryData(for: indexPath) - - if let id = id, let bakery = bakery { - navigateToDetailViewController(with: id) - logAnalytics(for: bakery) + if event == .didSelect { + handler(indexPath) } } - private func getBakeryData(for indexPath: IndexPath) -> (Int?, String?) { - switch indexPath.section { - case 0: - return (bakeryList[indexPath.item].overview.id, bakeryList[indexPath.item].overview.name) - case 1: - return (reviewList[indexPath.item].overview.id, reviewList[indexPath.item].overview.name) - default: - return (nil, nil) + func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { + if event == .didDeselect { + handler(indexPath) } } +} + +struct CollectionViewPublisher: Publisher { + typealias Output = IndexPath + typealias Failure = Never - private func navigateToDetailViewController(with id: Int) { - let nextViewController = BakeryDetailViewController() - nextViewController.bakeryID = id - navigationController?.isNavigationBarHidden = true - navigationController?.pushViewController(nextViewController, animated: true) - } + let collectionView: UICollectionView + let event: Event - private func logAnalytics(for bakery: String) { - AnalyticManager.log(event: .home(.clickRecommendStore(bakery: bakery))) - AnalyticManager.log(event: .detail(.viewDetailpageAt(source: AnalyticEventType.HOME.rawValue))) + func receive(subscriber: S) where S: Subscriber, S.Input == IndexPath, S.Failure == Never { + let subscription = CollectionViewSubscription( + subscriber: subscriber, + collectionView: collectionView, + event: event + ) + subscriber.receive(subscription: subscription) } } diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift index 51181e1b..3fb2cb60 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift @@ -16,15 +16,18 @@ final class HomeViewModel: ViewModelType { } struct Output { - let bakery: AnyPublisher<[BestBakery], Error> - let review: AnyPublisher<[BestReview], Error> + let bakery: AnyPublisher<[BestBakery], Never> + let review: AnyPublisher<[BestReview], Never> } // MARK: - Property private let usecase: HomeUseCase private var cancellable: Set = Set() - + + private var bakerySubject = CurrentValueSubject<[BestBakery], Never>([]) + private var reviewSubject = CurrentValueSubject<[BestReview], Never>([]) + init(usecase: HomeUseCase) { self.usecase = usecase } @@ -32,41 +35,34 @@ final class HomeViewModel: ViewModelType { // MARK: - func func transform(_ input: Input) -> Output { - let bakery = input.viewDidLoad - .compactMap { [weak self] in self } - .flatMap { _ -> AnyPublisher<[BestBakery], Error> in - Future<[BestBakery], Error> { promise in - Task { - do { - let bakery = try await self.fetchBestBakery() - promise(.success(bakery)) - } catch { - promise(.failure(error)) - } - } - } - .eraseToAnyPublisher() + input.viewDidLoad + .sink { [weak self] in + self?.fetchData() + } + .store(in: &cancellable) + + return Output(bakery: bakerySubject.eraseToAnyPublisher(), + review: reviewSubject.eraseToAnyPublisher()) + } + + private func fetchData() { + Task { + do { + let bakeries = try await fetchBestBakery() + bakerySubject.send(bakeries) + } catch { + bakerySubject.send([]) } - .eraseToAnyPublisher() + } - let review = input.viewDidLoad - .compactMap { [weak self] in self } - .flatMap { _ -> AnyPublisher<[BestReview], Error> in - return Future<[BestReview], Error> { promise in - Task { - do { - let review = try await self.fetchBestReview() - promise(.success(review)) - } catch { - promise(.failure(error)) - } - } - } - .eraseToAnyPublisher() + Task { + do { + let reviews = try await fetchBestReview() + reviewSubject.send(reviews) + } catch { + reviewSubject.send([]) } - .eraseToAnyPublisher() - - return Output(bakery: bakery, review: review) + } } } From b10436157afc46a32ee1065c07ce0205229228b2 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 21:44:23 +0900 Subject: [PATCH 26/31] =?UTF-8?q?[Fix]=20#275=20-=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift index c610e629..0209622e 100644 --- a/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift +++ b/GEON-PPANG-iOS/Domain/UseCase/HomeUseCase.swift @@ -18,10 +18,10 @@ final class HomeUseCaseImpl: HomeUseCase { let bestRepository: BestRepository - init(bestRepository: BestRepository) { + init(bestRepository: BestRepository) { self.bestRepository = bestRepository } - + func fetchBestBakeries() async throws -> [BestBakery] { do { return try await bestRepository.getBestBakeries() From 7a4c394361ff0d75ee90c1e25bc9b98b48725b2b Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 21:45:28 +0900 Subject: [PATCH 27/31] =?UTF-8?q?[Fix]=20#275=20-=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Home/Home/ViewController/NewHomeViewController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index 332b0b90..73e9d2aa 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -118,8 +118,8 @@ final class NewHomeViewController: UIViewController { output.bakery .receive(on: RunLoop.main) - .sink { err in - print("error:\(err)") + .sink { completion in + print("completion:\(completion)") } receiveValue: { [weak self] bakery in self?.reloadBestList(bakery: bakery) } @@ -127,8 +127,8 @@ final class NewHomeViewController: UIViewController { output.review .receive(on: RunLoop.main) - .sink { err in - print("error:\(err)") + .sink { completion in + print("completion:\(completion)") } receiveValue: { [weak self] review in self?.reloadBestList(review: review) } From ff6d7110ce6ef400cc78a3ca6f6b2cdf611da65a Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 21:46:05 +0900 Subject: [PATCH 28/31] =?UTF-8?q?[Fix]=20#275=20-=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Home/Home/ViewController/HomeViewController.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift index 27d4267d..e0d1bc77 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/HomeViewController.swift @@ -330,9 +330,3 @@ extension HomeViewController { } } } - - -final class HomeCompositionalLayout: UICollectionViewCompositionalLayout { - - -} From eeb5ffad45624df9c3da25ac110b1e1e014fbc21 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 22:14:02 +0900 Subject: [PATCH 29/31] =?UTF-8?q?[Fix]=20#275=20-=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scene/Home/Home/ViewModel/HomeViewModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift index 3fb2cb60..19412625 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewModel/HomeViewModel.swift @@ -25,8 +25,8 @@ final class HomeViewModel: ViewModelType { private let usecase: HomeUseCase private var cancellable: Set = Set() - private var bakerySubject = CurrentValueSubject<[BestBakery], Never>([]) - private var reviewSubject = CurrentValueSubject<[BestReview], Never>([]) + private var bakerySubject = PassthroughSubject<[BestBakery], Never>() + private var reviewSubject = PassthroughSubject<[BestReview], Never>() init(usecase: HomeUseCase) { self.usecase = usecase From 8c956a0d9d17434239102602f576dc32ff36fac2 Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 22:19:43 +0900 Subject: [PATCH 30/31] =?UTF-8?q?[Fix]=20#275=20-=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 8 ++++---- ...ne.swift => UIViewController+LifeCyclePublisher.swift} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/{UIViewController+Combine.swift => UIViewController+LifeCyclePublisher.swift} (100%) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 986a2272..571ca132 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -81,7 +81,7 @@ 098716B62A60F52200538D05 /* BakeryTypeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098716B52A60F52200538D05 /* BakeryTypeProtocol.swift */; }; 098716B82A6138BD00538D05 /* MyReviewsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098716B72A6138BD00538D05 /* MyReviewsHeaderView.swift */; }; 0987288D2A5BA1F000A29402 /* BookmarkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0987288C2A5BA1F000A29402 /* BookmarkButton.swift */; }; - 098800A82C4E3A62009E6F43 /* UIViewController+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */; }; + 098800A82C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 098800A72C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift */; }; 098F32EA2A4200FE0092D09A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 098F32E92A4200FE0092D09A /* Assets.xcassets */; }; 098F32ED2A4200FE0092D09A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 098F32EB2A4200FE0092D09A /* LaunchScreen.storyboard */; }; 09980CFB2A99A9800098550C /* SignInPropertyType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09980CFA2A99A9800098550C /* SignInPropertyType.swift */; }; @@ -400,7 +400,7 @@ 098716B52A60F52200538D05 /* BakeryTypeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BakeryTypeProtocol.swift; sourceTree = ""; }; 098716B72A6138BD00538D05 /* MyReviewsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyReviewsHeaderView.swift; sourceTree = ""; }; 0987288C2A5BA1F000A29402 /* BookmarkButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkButton.swift; sourceTree = ""; }; - 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Combine.swift"; sourceTree = ""; }; + 098800A72C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+LifeCyclePublisher.swift"; sourceTree = ""; }; 098F32DD2A4200FD0092D09A /* GEON-PPANG-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GEON-PPANG-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 098F32E02A4200FD0092D09A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 098F32E22A4200FD0092D09A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -1041,7 +1041,7 @@ 098800A62C4E3A4D009E6F43 /* Combine */ = { isa = PBXGroup; children = ( - 098800A72C4E3A62009E6F43 /* UIViewController+Combine.swift */, + 098800A72C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift */, ); path = Combine; sourceTree = ""; @@ -2362,7 +2362,7 @@ 3E3DE9C92C25AE0100CA5999 /* PasswordValidationError.swift in Sources */, 0959F1702A658CA400E77CAF /* HomeBestBakeryResponseDTO.swift in Sources */, 3E7B21C42A621A9A00C8F8B4 /* SortBakeryCollectionViewCell.swift in Sources */, - 098800A82C4E3A62009E6F43 /* UIViewController+Combine.swift in Sources */, + 098800A82C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift in Sources */, DFB587BB2A5D588500704B6C /* DrawDashLineView.swift in Sources */, 090556222A51DB3300752067 /* UIFont+.swift in Sources */, 092698892C3CF93F00A9349D /* BestBakeryResponseDTO.swift in Sources */, diff --git a/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift b/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+LifeCyclePublisher.swift similarity index 100% rename from GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+Combine.swift rename to GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+LifeCyclePublisher.swift From 2b1fb4ea97c18075ef864ce7bb8dc05ee27b027b Mon Sep 17 00:00:00 2001 From: jeongdung-eo Date: Tue, 13 Aug 2024 22:26:48 +0900 Subject: [PATCH 31/31] =?UTF-8?q?[Fix]=20#275=20-=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GEON-PPANG-iOS.xcodeproj/project.pbxproj | 38 +++++++++- .../NewHomeViewController.swift | 74 ------------------- .../Publisher/CollectionViewPublisher.swift | 28 +++++++ .../CollectionViewSubscription.swift | 69 +++++++++++++++++ .../UIViewController+LifeCyclePublisher.swift | 0 5 files changed, 132 insertions(+), 77 deletions(-) create mode 100644 GEON-PPANG-iOS/Presentation/Utils/Combine/Publisher/CollectionViewPublisher.swift create mode 100644 GEON-PPANG-iOS/Presentation/Utils/Combine/Subscription/CollectionViewSubscription.swift rename GEON-PPANG-iOS/Presentation/Utils/Extension/{Combine => UIViewController}/UIViewController+LifeCyclePublisher.swift (100%) diff --git a/GEON-PPANG-iOS.xcodeproj/project.pbxproj b/GEON-PPANG-iOS.xcodeproj/project.pbxproj index 571ca132..feddcab3 100644 --- a/GEON-PPANG-iOS.xcodeproj/project.pbxproj +++ b/GEON-PPANG-iOS.xcodeproj/project.pbxproj @@ -44,6 +44,8 @@ 0930D2632A93292F00A75C7E /* IconWithTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0930D2622A93292F00A75C7E /* IconWithTextView.swift */; }; 093214022A5AE27800875EF6 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093214012A5AE27700875EF6 /* Utils.swift */; }; 093214082A5AE40900875EF6 /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093214072A5AE40900875EF6 /* SearchViewController.swift */; }; + 093DC89F2C6B95A100DE6EA2 /* CollectionViewSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093DC89E2C6B95A100DE6EA2 /* CollectionViewSubscription.swift */; }; + 093DC8A22C6B95FC00DE6EA2 /* CollectionViewPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093DC8A12C6B95FC00DE6EA2 /* CollectionViewPublisher.swift */; }; 093EFA592A61F62D003228CD /* SignInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093EFA582A61F62D003228CD /* SignInViewController.swift */; }; 094392CF2A84E68700984310 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 094392CE2A84E68700984310 /* GoogleService-Info.plist */; }; 0943B9302AB610A8006EC1DE /* AnalyticEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0943B92F2AB610A8006EC1DE /* AnalyticEventType.swift */; }; @@ -365,6 +367,8 @@ 0930D2622A93292F00A75C7E /* IconWithTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconWithTextView.swift; sourceTree = ""; }; 093214012A5AE27700875EF6 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 093214072A5AE40900875EF6 /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = ""; }; + 093DC89E2C6B95A100DE6EA2 /* CollectionViewSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewSubscription.swift; sourceTree = ""; }; + 093DC8A12C6B95FC00DE6EA2 /* CollectionViewPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewPublisher.swift; sourceTree = ""; }; 093EFA582A61F62D003228CD /* SignInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInViewController.swift; sourceTree = ""; }; 094392CE2A84E68700984310 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 0943B92F2AB610A8006EC1DE /* AnalyticEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticEventType.swift; sourceTree = ""; }; @@ -770,6 +774,31 @@ path = ViewController; sourceTree = ""; }; + 093DC89C2C6B950900DE6EA2 /* Combine */ = { + isa = PBXGroup; + children = ( + 093DC8A02C6B95F100DE6EA2 /* Publisher */, + 093DC89D2C6B958F00DE6EA2 /* Subscription */, + ); + path = Combine; + sourceTree = ""; + }; + 093DC89D2C6B958F00DE6EA2 /* Subscription */ = { + isa = PBXGroup; + children = ( + 093DC89E2C6B95A100DE6EA2 /* CollectionViewSubscription.swift */, + ); + path = Subscription; + sourceTree = ""; + }; + 093DC8A02C6B95F100DE6EA2 /* Publisher */ = { + isa = PBXGroup; + children = ( + 093DC8A12C6B95FC00DE6EA2 /* CollectionViewPublisher.swift */, + ); + path = Publisher; + sourceTree = ""; + }; 093EFA542A61F5E4003228CD /* SignIn */ = { isa = PBXGroup; children = ( @@ -1033,17 +1062,17 @@ 098800A52C4E3A3B009E6F43 /* Extension */ = { isa = PBXGroup; children = ( - 098800A62C4E3A4D009E6F43 /* Combine */, + 098800A62C4E3A4D009E6F43 /* UIViewController */, ); path = Extension; sourceTree = ""; }; - 098800A62C4E3A4D009E6F43 /* Combine */ = { + 098800A62C4E3A4D009E6F43 /* UIViewController */ = { isa = PBXGroup; children = ( 098800A72C4E3A62009E6F43 /* UIViewController+LifeCyclePublisher.swift */, ); - path = Combine; + path = UIViewController; sourceTree = ""; }; 098F32D42A4200FD0092D09A = { @@ -1516,6 +1545,7 @@ 3E8C47E02BC3B81B00919E06 /* Utils */ = { isa = PBXGroup; children = ( + 093DC89C2C6B950900DE6EA2 /* Combine */, 098800A52C4E3A3B009E6F43 /* Extension */, 3E8C47E12BC3B82500919E06 /* DummyUIUtils.swift */, ); @@ -2416,6 +2446,7 @@ 3E3543302AAC700600BD926A /* SignUpRequestDTO.swift in Sources */, 3E8C47EF2BC3C9EA00919E06 /* MainCoordinator.swift in Sources */, 0987288D2A5BA1F000A29402 /* BookmarkButton.swift in Sources */, + 093DC8A22C6B95FC00DE6EA2 /* CollectionViewPublisher.swift in Sources */, 3E3DE9D02C25AE5900CA5999 /* BestBakery.swift in Sources */, 090556202A51DB2C00752067 /* UIImage+.swift in Sources */, 3E1E74012B78AD530082386A /* BookmarkBakeryListResponseDTO.swift in Sources */, @@ -2493,6 +2524,7 @@ 095FB8842AB3435300C69BD1 /* AnalyticManagerProtocol.swift in Sources */, 3E3DE9E72C25AF8500CA5999 /* Reviews.swift in Sources */, 3E3DE9BF2C25AD7000CA5999 /* NutrientType.swift in Sources */, + 093DC89F2C6B95A100DE6EA2 /* CollectionViewSubscription.swift in Sources */, 3E162D182A692C1400590C6F /* BookmarkRequestDTO.swift in Sources */, 3E3DE9DD2C25AEF400CA5999 /* Menu.swift in Sources */, 0930D25F2A928C2300A75C7E /* RecommendKeywordResponseDTO.swift in Sources */, diff --git a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift index 73e9d2aa..5702b536 100644 --- a/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift +++ b/GEON-PPANG-iOS/Presentation/Scene/Home/Home/ViewController/NewHomeViewController.swift @@ -328,77 +328,3 @@ extension NewHomeViewController { return [header] } } - -enum Event { - case didSelect - case didDeselect -} - -final class CollectionViewSubscription: Subscription where SubscriberType.Input == IndexPath { - private var subscriber: SubscriberType? - private weak var collectionView: UICollectionView? - private var delegateProxy: CollectionViewDelegateProxy? - - init(subscriber: SubscriberType, collectionView: UICollectionView, event: Event) { - self.subscriber = subscriber - self.collectionView = collectionView - - let delegateProxy = CollectionViewDelegateProxy( - event: event, - handler: { [weak self] indexPath in - _ = self?.subscriber?.receive(indexPath) - } - ) - - self.delegateProxy = delegateProxy - collectionView.delegate = delegateProxy - } - - func request(_ demand: Subscribers.Demand) { - // 요구 처리 로직 추가 가능 - } - - func cancel() { - subscriber = nil - delegateProxy = nil - } -} - -private class CollectionViewDelegateProxy: NSObject, UICollectionViewDelegate { - private let event: Event - private let handler: (IndexPath) -> Void - - init(event: Event, handler: @escaping (IndexPath) -> Void) { - self.event = event - self.handler = handler - } - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - if event == .didSelect { - handler(indexPath) - } - } - - func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { - if event == .didDeselect { - handler(indexPath) - } - } -} - -struct CollectionViewPublisher: Publisher { - typealias Output = IndexPath - typealias Failure = Never - - let collectionView: UICollectionView - let event: Event - - func receive(subscriber: S) where S: Subscriber, S.Input == IndexPath, S.Failure == Never { - let subscription = CollectionViewSubscription( - subscriber: subscriber, - collectionView: collectionView, - event: event - ) - subscriber.receive(subscription: subscription) - } -} diff --git a/GEON-PPANG-iOS/Presentation/Utils/Combine/Publisher/CollectionViewPublisher.swift b/GEON-PPANG-iOS/Presentation/Utils/Combine/Publisher/CollectionViewPublisher.swift new file mode 100644 index 00000000..b9379e46 --- /dev/null +++ b/GEON-PPANG-iOS/Presentation/Utils/Combine/Publisher/CollectionViewPublisher.swift @@ -0,0 +1,28 @@ +// +// CollectionViewPublisher.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 8/13/24. +// + +import Combine + +import UIKit + +struct CollectionViewPublisher: Publisher { + typealias Output = IndexPath + typealias Failure = Never + + let collectionView: UICollectionView + let event: Event + + func receive(subscriber: S) where S: Subscriber, S.Input == IndexPath, S.Failure == Never { + let subscription = CollectionViewSubscription( + subscriber: subscriber, + collectionView: collectionView, + event: event + ) + subscriber.receive(subscription: subscription) + } +} + diff --git a/GEON-PPANG-iOS/Presentation/Utils/Combine/Subscription/CollectionViewSubscription.swift b/GEON-PPANG-iOS/Presentation/Utils/Combine/Subscription/CollectionViewSubscription.swift new file mode 100644 index 00000000..fc53670e --- /dev/null +++ b/GEON-PPANG-iOS/Presentation/Utils/Combine/Subscription/CollectionViewSubscription.swift @@ -0,0 +1,69 @@ +// +// CollectionViewSubscription.swift +// GEON-PPANG-iOS +// +// Created by JEONGEUN KIM on 8/13/24. +// + +import Combine + +import UIKit + + +enum Event { + case didSelect + case didDeselect +} + +final class CollectionViewSubscription: Subscription where SubscriberType.Input == IndexPath { + private var subscriber: SubscriberType? + private weak var collectionView: UICollectionView? + private var delegateProxy: CollectionViewDelegateProxy? + + init(subscriber: SubscriberType, collectionView: UICollectionView, event: Event) { + self.subscriber = subscriber + self.collectionView = collectionView + + let delegateProxy = CollectionViewDelegateProxy( + event: event, + handler: { [weak self] indexPath in + _ = self?.subscriber?.receive(indexPath) + } + ) + + self.delegateProxy = delegateProxy + collectionView.delegate = delegateProxy + } + + func request(_ demand: Subscribers.Demand) { + // 요구 처리 로직 추가 가능 + } + + func cancel() { + subscriber = nil + delegateProxy = nil + } +} + + +private class CollectionViewDelegateProxy: NSObject, UICollectionViewDelegate { + private let event: Event + private let handler: (IndexPath) -> Void + + init(event: Event, handler: @escaping (IndexPath) -> Void) { + self.event = event + self.handler = handler + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if event == .didSelect { + handler(indexPath) + } + } + + func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { + if event == .didDeselect { + handler(indexPath) + } + } +} diff --git a/GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+LifeCyclePublisher.swift b/GEON-PPANG-iOS/Presentation/Utils/Extension/UIViewController/UIViewController+LifeCyclePublisher.swift similarity index 100% rename from GEON-PPANG-iOS/Presentation/Utils/Extension/Combine/UIViewController+LifeCyclePublisher.swift rename to GEON-PPANG-iOS/Presentation/Utils/Extension/UIViewController/UIViewController+LifeCyclePublisher.swift