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