From 6eb97ea93ea13ac63eee0186b0cb20c806d09220 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 3 Jul 2024 21:42:38 +0900 Subject: [PATCH 01/13] =?UTF-8?q?Feat:=20RecipeDetailDTO=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/DTO/RecipeDetailDTO.swift | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift new file mode 100644 index 0000000..0c11bfa --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/DTO/RecipeDetailDTO.swift @@ -0,0 +1,49 @@ +// +// RecipeDetailDTO.swift +// HomeCafeRecipes +// +// Created by 김건호 on 6/29/24. +// + +import Foundation + +struct RecipeDetailDTO: Decodable { + + let id: Int + let type: String + let name: String + let description: String + let likesCount: Int + let createdAt: String + let writer: UserDTO + let imageUrls: [RecipeImageDTO] + let isLikedByCurrentUser: Bool + + enum CodingKeys: String, CodingKey { + case id = "recipeId" + case type = "recipeType" + case name = "recipeName" + case description = "recipeDescription" + case likesCount = "recipeLikesCnt" + case createdAt = "createdAt" + case writer = "writer" + case imageUrls = "recipeImgUrls" + case isLikedByCurrentUser = "isLiked" + } +} + +extension RecipeDetailDTO { + func toDomain() -> Recipe { + return Recipe( + id: id, + type: RecipeType(rawValue: type) ?? .coffee, + name: name, + description: description, + writer: writer.toDomain(), + imageUrls: imageUrls.map { $0.recipeImageUrl }, + isLikedByCurrentUser: isLikedByCurrentUser, + likeCount: likesCount, + createdAt: DateFormatter.iso8601.date(from: createdAt) ?? Date() + ) + } +} From bab43debb385ad4cae750feccaec3471f03f48ce Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 3 Jul 2024 21:42:56 +0900 Subject: [PATCH 02/13] =?UTF-8?q?Feat:=20RecipeDetailFetchService=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Network/RecipeDetailFetchService.swift | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift new file mode 100644 index 0000000..867bd93 --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift @@ -0,0 +1,34 @@ +// +// RecipeDetailFetchService.swift +// HomeCafeRecipes +// +// Created by 김건호 on 6/26/24. +// + +import Foundation +import RxSwift + +protocol RecipeDetailFetchService { + func fetchRecipeDetail(recipeId: Int) -> Single +} + +class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { + private let networkService: NetworkService + private static let baseURL: URL = URL(string: "https://meog0.store/api")! + + init(networkService: NetworkService) { + self.networkService = networkService + } + + private func makeURL(recipeId: Int) -> URL? { + return RecipeDetailFetchServiceImpl.baseURL.appendingPathComponent("recipes/\(recipeId)") + } + + func fetchRecipeDetail(recipeId: Int) -> Single { + guard let URL = makeURL(recipeId: recipeId) else { + return Single.error(NSError(domain: "URLComponentsError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) + } + return networkService.getRequest(url: URL, responseType: NetworkResponseDTO.self) + .map { $0.data.toDomain() } + } +} From 4b09f04e11fcc086f724f2b51be25ccb7e41a77f Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 3 Jul 2024 21:43:19 +0900 Subject: [PATCH 03/13] =?UTF-8?q?Feat:=20RecipeDetailRepository=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repositories/RecipeDetailRepository.swift | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift new file mode 100644 index 0000000..fd409b4 --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift @@ -0,0 +1,25 @@ +// +// RecipeDetailRepository.swift +// HomeCafeRecipes +// +// Created by 김건호 on 6/26/24. +// + +import Foundation +import RxSwift + +protocol RecipeDetailRepository { + func fetchRecipeDetail(recipeID: Int) -> Single +} + +class FeedListRepositoryImpl: RecipeDetailRepository { + private let networkService: RecipeDetailFetchService + + init(networkService: RecipeDetailFetchService) { + self.networkService = networkService + } + + func fetchRecipeDetail(recipeID: Int) -> Single { + return networkService.fetchRecipeDetail(recipeId: recipeID) + } +} From 3f7f570de02de267bb5d7925127eb57fb6e19f5d Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 3 Jul 2024 21:44:33 +0900 Subject: [PATCH 04/13] =?UTF-8?q?Feat:=20FetchRecipeDetailUseCase=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UseCases/FetchRecipeDetailUseCase.swift | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchRecipeDetailUseCase.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchRecipeDetailUseCase.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchRecipeDetailUseCase.swift new file mode 100644 index 0000000..5edd588 --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchRecipeDetailUseCase.swift @@ -0,0 +1,31 @@ +// +// FetchRecipeDetailUseCase.swift +// HomeCafeRecipes +// +// Created by 김건호 on 6/26/24. +// + +import Foundation +import RxSwift + +protocol FetchRecipeDetailUseCase { + func execute(recipeID: Int) -> Single> +} + +class FetchRecipeDetailUseCaseImpl: FetchRecipeDetailUseCase { + private let repository: RecipeDetailRepository + + init(repository: RecipeDetailRepository) { + self.repository = repository + } + + func execute(recipeID: Int) -> Single> { + return repository.fetchRecipeDetail(recipeID: recipeID) + .map { recipe in + return .success(recipe) + } + .catch { error in + return .just(.failure(error)) + } + } +} From 429a9626c19675402f8f6fad490b4a343d0a5754 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 3 Jul 2024 21:45:04 +0900 Subject: [PATCH 05/13] =?UTF-8?q?Feat:=20RecipeDetailInteractor=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interactor/RecipeDetailInteractor.swift | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift new file mode 100644 index 0000000..e1f2755 --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift @@ -0,0 +1,73 @@ +// +// RecipeDetailInteractor.swift +// HomeCafeRecipes +// +// Created by 김건호 on 6/27/24. +// + +import Foundation +import RxSwift + +protocol RecipeDetailInteractorDelegate: AnyObject { + func fetchedRecipe(result: Result) +} + +protocol InputRecipeDetailInteractor { + func viewDidLoad() +} + +protocol OutputRecipeDetailInteractor { + var recipe: Observable> { get } +} + +class RecipeDetailInteractor: InputRecipeDetailInteractor, OutputRecipeDetailInteractor { + + private let fetchRecipeDetailUseCase: FetchRecipeDetailUseCase + private let recipeID: Int + private let disposeBag = DisposeBag() + private let recipeDetailSubject = PublishSubject>() + weak var delegate: RecipeDetailInteractorDelegate? + + var recipe: Observable> { + return recipeDetailSubject.asObservable() + } + + init(fetchRecipeDetailUseCase: FetchRecipeDetailUseCase, recipeID: Int) { + self.fetchRecipeDetailUseCase = fetchRecipeDetailUseCase + self.recipeID = recipeID + } + + func setDelegate(_ delegate: RecipeDetailInteractorDelegate) { + self.delegate = delegate + bindOutputs() + } + + private func bindOutputs() { + recipe + .subscribe(onNext: { [weak self] result in + self?.delegate?.fetchedRecipe(result: result) + }) + .disposed(by: disposeBag) + } + + func viewDidLoad() { + fetchRecipeDetail() + } + + private func fetchRecipeDetail() { + fetchRecipeDetailUseCase.execute(recipeID: recipeID) + .subscribe { [weak self] result in + self?.handleResult(result) + } + .disposed(by: disposeBag) + } + + private func handleResult(_ result: Result) { + switch result { + case .success(let recipe): + self.recipeDetailSubject.onNext(.success(recipe)) + case .failure(let error): + self.recipeDetailSubject.onNext(.failure(error)) + } + } +} From 6178184f65b245b58ce4b42e2c9f97801f65c14f Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Fri, 5 Jul 2024 13:43:25 +0900 Subject: [PATCH 06/13] =?UTF-8?q?Fix:=20recipeID=EB=A1=9C=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/RecipeDetailFetchService.swift | 10 +++++----- .../Data/Repositories/RecipeDetailRepository.swift | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift index 867bd93..38226e5 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift @@ -9,7 +9,7 @@ import Foundation import RxSwift protocol RecipeDetailFetchService { - func fetchRecipeDetail(recipeId: Int) -> Single + func fetchRecipeDetail(recipeID: Int) -> Single } class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { @@ -20,12 +20,12 @@ class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { self.networkService = networkService } - private func makeURL(recipeId: Int) -> URL? { - return RecipeDetailFetchServiceImpl.baseURL.appendingPathComponent("recipes/\(recipeId)") + private func makeURL(recipeID: Int) -> URL? { + return RecipeDetailFetchServiceImpl.baseURL.appendingPathComponent("recipes/\(recipeID)") } - func fetchRecipeDetail(recipeId: Int) -> Single { - guard let URL = makeURL(recipeId: recipeId) else { + func fetchRecipeDetail(recipeID: Int) -> Single { + guard let URL = makeURL(recipeID: recipeID) else { return Single.error(NSError(domain: "URLComponentsError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) } return networkService.getRequest(url: URL, responseType: NetworkResponseDTO.self) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift index fd409b4..a8ea888 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift @@ -20,6 +20,6 @@ class FeedListRepositoryImpl: RecipeDetailRepository { } func fetchRecipeDetail(recipeID: Int) -> Single { - return networkService.fetchRecipeDetail(recipeId: recipeID) + return networkService.fetchRecipeDetail(recipeID: recipeID) } } From e1176294b86f41fa02b03a5f6d11eeeee31a1dc5 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Fri, 5 Jul 2024 15:09:01 +0900 Subject: [PATCH 07/13] =?UTF-8?q?Fix:=20RecipeDetailFetchServiceImpl=20fin?= =?UTF-8?q?al=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift index 38226e5..56af1c7 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift @@ -12,7 +12,7 @@ protocol RecipeDetailFetchService { func fetchRecipeDetail(recipeID: Int) -> Single } -class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { +final class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { private let networkService: NetworkService private static let baseURL: URL = URL(string: "https://meog0.store/api")! From 8f79c55789e77d585be6017fb3e93ed92f4b18cd Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Fri, 5 Jul 2024 15:39:14 +0900 Subject: [PATCH 08/13] =?UTF-8?q?Feat:=20RecipeError=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/Entities/RecipeError.swift | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift new file mode 100644 index 0000000..fbb4c94 --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift @@ -0,0 +1,30 @@ +// +// RecipeError.swift +// HomeCafeRecipes +// +// Created by 김건호 on 7/5/24. +// + +import Foundation + +enum RecipeError: Error { + case invalidURL + case networkError(Error) + case decodingError + case unknownError +} + +extension RecipeError: LocalizedError { + var errorDescription: String? { + switch self { + case .invalidURL: + return "Invalid URL" + case .networkError(let error): + return error.localizedDescription + case .decodingError: + return "Failed to decode the response" + case .unknownError: + return "An unknown error occurred" + } + } +} From c91393f66ef5f0ecf73e01aa391af33d038eddd6 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Fri, 5 Jul 2024 15:39:36 +0900 Subject: [PATCH 09/13] =?UTF-8?q?Fix:=20=EC=A0=95=EC=9D=98=EB=90=9C=20Erro?= =?UTF-8?q?r=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Data/Network/RecipeDetailFetchService.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift index 56af1c7..e3f1ec7 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift @@ -25,10 +25,16 @@ final class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { } func fetchRecipeDetail(recipeID: Int) -> Single { - guard let URL = makeURL(recipeID: recipeID) else { - return Single.error(NSError(domain: "URLComponentsError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) + guard let url = makeURL(recipeID: recipeID) else { + return Single.error(RecipeError.invalidURL) } - return networkService.getRequest(url: URL, responseType: NetworkResponseDTO.self) + return networkService.getRequest(url: url, responseType: NetworkResponseDTO.self) .map { $0.data.toDomain() } + .catch { error in + guard let decodingError = error as? DecodingError else { + return Single.error(RecipeError.networkError(error)) + } + return Single.error(RecipeError.decodingError) + } } } From 9ba86205c9e3b20f1e89b49d5567bc19bae1be77 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Fri, 5 Jul 2024 16:47:53 +0900 Subject: [PATCH 10/13] =?UTF-8?q?Fix:=20=EA=B0=9C=ED=96=89=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/Interactor/RecipeDetailInteractor.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift index e1f2755..187863f 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/Interactor/RecipeDetailInteractor.swift @@ -32,7 +32,10 @@ class RecipeDetailInteractor: InputRecipeDetailInteractor, OutputRecipeDetailInt return recipeDetailSubject.asObservable() } - init(fetchRecipeDetailUseCase: FetchRecipeDetailUseCase, recipeID: Int) { + init( + fetchRecipeDetailUseCase: FetchRecipeDetailUseCase, + recipeID: Int + ) { self.fetchRecipeDetailUseCase = fetchRecipeDetailUseCase self.recipeID = recipeID } From ed07510ebadc919443019a9445f6dd5b48b8725e Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Mon, 8 Jul 2024 23:22:22 +0900 Subject: [PATCH 11/13] =?UTF-8?q?Fix:=20RecipeDetailError=EB=A1=9C=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeCafeRecipes.xcodeproj/project.pbxproj | 188 +++++++++++++----- .../Network/RecipeDetailFetchService.swift | 6 +- ...ipeError.swift => RecipeDetailError.swift} | 4 +- 3 files changed, 141 insertions(+), 57 deletions(-) rename HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/{RecipeError.swift => RecipeDetailError.swift} (88%) diff --git a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj index b1eecef..c0ef8ae 100644 --- a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj +++ b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj @@ -9,15 +9,12 @@ /* Begin PBXBuildFile section */ 1D1283A22C15E94300C5A870 /* Recipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A12C15E94300C5A870 /* Recipe.swift */; }; 1D1283A42C15EA8100C5A870 /* RecipeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A32C15EA8100C5A870 /* RecipeType.swift */; }; - 1D1283A62C15EAA600C5A870 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A52C15EAA600C5A870 /* User.swift */; }; - 1D1283A82C15EABB00C5A870 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A72C15EABB00C5A870 /* Comment.swift */; }; 1D1283AA2C15EBCF00C5A870 /* SearchFeedUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283A92C15EBCF00C5A870 /* SearchFeedUseCase.swift */; }; 1D1283AC2C15EBE600C5A870 /* FetchFeedListUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283AB2C15EBE600C5A870 /* FetchFeedListUseCase.swift */; }; 1D1283AF2C1697DB00C5A870 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 1D1283AE2C1697DB00C5A870 /* RxCocoa */; }; 1D1283B12C1697DB00C5A870 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 1D1283B02C1697DB00C5A870 /* RxSwift */; }; 1D1283B42C16983900C5A870 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 1D1283B32C16983900C5A870 /* RxSwift */; }; 1D1283B62C16984E00C5A870 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 1D1283B52C16984E00C5A870 /* RxCocoa */; }; - 1D1283C82C16CE7C00C5A870 /* DateFormatter+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283C72C16CE7C00C5A870 /* DateFormatter+Extensions.swift */; }; 1D1283CA2C16D9C600C5A870 /* RecipeFetchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1283C92C16D9C600C5A870 /* RecipeFetchService.swift */; }; 1D2C16E62BE532B700C04508 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D2C16E52BE532B700C04508 /* AppDelegate.swift */; }; 1D2C16EA2BE532B700C04508 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D2C16E92BE532B700C04508 /* ViewController.swift */; }; @@ -28,14 +25,30 @@ 1D4741D22C1B4F8D009381CE /* RecipeDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CD2C1B4F8D009381CE /* RecipeDTO.swift */; }; 1D4741D32C1B4F8D009381CE /* RecipePageDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CE2C1B4F8D009381CE /* RecipePageDTO.swift */; }; 1D4741D42C1B4F8D009381CE /* NetworkResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CF2C1B4F8D009381CE /* NetworkResponseDTO.swift */; }; - 1D4741D52C1B4F8D009381CE /* UserDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741D02C1B4F8D009381CE /* UserDTO.swift */; }; - 1DDFFD812C1C096A0083B077 /* RecipeMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DDFFD802C1C096A0083B077 /* RecipeMapper.swift */; }; + 1D7368B72C3442C8000EF904 /* String+Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B52C3442C8000EF904 /* String+Validation.swift */; }; + 1D7368B82C3442C8000EF904 /* UIImageViewImageLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B62C3442C8000EF904 /* UIImageViewImageLoading.swift */; }; + 1D7368BA2C3442DE000EF904 /* RecipeListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B92C3442DE000EF904 /* RecipeListMapper.swift */; }; + 1D7368C72C344378000EF904 /* UserDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368C62C344378000EF904 /* UserDTO.swift */; }; + 1D7368CA2C3443A1000EF904 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368C82C3443A1000EF904 /* Comment.swift */; }; + 1D7368CB2C3443A1000EF904 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368C92C3443A1000EF904 /* User.swift */; }; + 1D7368CE2C344403000EF904 /* DateFormatter+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368CD2C344403000EF904 /* DateFormatter+Extensions.swift */; }; + 1D7368D22C34FADD000EF904 /* FetchRecipeDetailUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D12C34FADD000EF904 /* FetchRecipeDetailUseCase.swift */; }; + 1D7368D42C34FAE8000EF904 /* RecipeDetailInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D32C34FAE8000EF904 /* RecipeDetailInteractor.swift */; }; + 1D7368D62C34FAF9000EF904 /* RecipeDetailFetchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */; }; + 1D7368D82C34FB07000EF904 /* RecipeDetailDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D72C34FB07000EF904 /* RecipeDetailDTO.swift */; }; + 1D7368DA2C34FB14000EF904 /* RecipeDetailRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D92C34FB14000EF904 /* RecipeDetailRepository.swift */; }; + 1D7368DC2C34FB32000EF904 /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368DB2C34FB32000EF904 /* CustomNavigationBar.swift */; }; + 1D7368E22C34FB38000EF904 /* RecipeDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368DF2C34FB38000EF904 /* RecipeDetailViewController.swift */; }; + 1D7368E32C34FB38000EF904 /* RecipeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E02C34FB38000EF904 /* RecipeDetailView.swift */; }; + 1D7368E42C34FB38000EF904 /* RecipeDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E12C34FB38000EF904 /* RecipeDetailViewModel.swift */; }; + 1D7368E72C34FB66000EF904 /* RecipeDetailCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E62C34FB66000EF904 /* RecipeDetailCoordinator.swift */; }; + 1D7368EA2C34FBF7000EF904 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E92C34FBF7000EF904 /* MainTabBarController.swift */; }; + 1D95A0A42C37B0E200F09077 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D95A0A32C37B0E200F09077 /* Fonts.swift */; }; + 1D95A0A82C37C7D400F09077 /* RecipeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D95A0A72C37C7D400F09077 /* RecipeError.swift */; }; 1DE19E9D2C1B3DC10031804A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19E9C2C1B3DC10031804A /* SceneDelegate.swift */; }; 1DE19EA72C1B420A0031804A /* FeedListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EA52C1B420A0031804A /* FeedListRepository.swift */; }; 1DE19EA82C1B420A0031804A /* SearchFeedListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EA62C1B420A0031804A /* SearchFeedListRepository.swift */; }; 1DE19EB12C1B42200031804A /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EB02C1B42200031804A /* NetworkService.swift */; }; - 1DE19EBF2C1B422F0031804A /* RecipeItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EB42C1B422F0031804A /* RecipeItemViewModel.swift */; }; - 1DE19EC02C1B422F0031804A /* RecipeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EB62C1B422F0031804A /* RecipeDetailView.swift */; }; 1DE19EC22C1B422F0031804A /* RecipeListItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EBA2C1B422F0031804A /* RecipeListItemViewModel.swift */; }; 1DE19EC32C1B422F0031804A /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EBB2C1B422F0031804A /* SearchBar.swift */; }; 1DE19EC42C1B422F0031804A /* RecipeListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EBC2C1B422F0031804A /* RecipeListViewController.swift */; }; @@ -65,11 +78,8 @@ /* Begin PBXFileReference section */ 1D1283A12C15E94300C5A870 /* Recipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recipe.swift; sourceTree = ""; }; 1D1283A32C15EA8100C5A870 /* RecipeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeType.swift; sourceTree = ""; }; - 1D1283A52C15EAA600C5A870 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; - 1D1283A72C15EABB00C5A870 /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; 1D1283A92C15EBCF00C5A870 /* SearchFeedUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchFeedUseCase.swift; sourceTree = ""; }; 1D1283AB2C15EBE600C5A870 /* FetchFeedListUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchFeedListUseCase.swift; sourceTree = ""; }; - 1D1283C72C16CE7C00C5A870 /* DateFormatter+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extensions.swift"; sourceTree = ""; }; 1D1283C92C16D9C600C5A870 /* RecipeFetchService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeFetchService.swift; sourceTree = ""; }; 1D2C16E22BE532B700C04508 /* HomeCafeRecipes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HomeCafeRecipes.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1D2C16E52BE532B700C04508 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -86,14 +96,30 @@ 1D4741CD2C1B4F8D009381CE /* RecipeDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDTO.swift; sourceTree = ""; }; 1D4741CE2C1B4F8D009381CE /* RecipePageDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipePageDTO.swift; sourceTree = ""; }; 1D4741CF2C1B4F8D009381CE /* NetworkResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkResponseDTO.swift; sourceTree = ""; }; - 1D4741D02C1B4F8D009381CE /* UserDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDTO.swift; sourceTree = ""; }; - 1DDFFD802C1C096A0083B077 /* RecipeMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipeMapper.swift; sourceTree = ""; }; + 1D7368B52C3442C8000EF904 /* String+Validation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Validation.swift"; sourceTree = ""; }; + 1D7368B62C3442C8000EF904 /* UIImageViewImageLoading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageViewImageLoading.swift; sourceTree = ""; }; + 1D7368B92C3442DE000EF904 /* RecipeListMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeListMapper.swift; sourceTree = ""; }; + 1D7368C62C344378000EF904 /* UserDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDTO.swift; sourceTree = ""; }; + 1D7368C82C3443A1000EF904 /* Comment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; + 1D7368C92C3443A1000EF904 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; + 1D7368CD2C344403000EF904 /* DateFormatter+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extensions.swift"; sourceTree = ""; }; + 1D7368D12C34FADD000EF904 /* FetchRecipeDetailUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchRecipeDetailUseCase.swift; sourceTree = ""; }; + 1D7368D32C34FAE8000EF904 /* RecipeDetailInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailInteractor.swift; sourceTree = ""; }; + 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailFetchService.swift; sourceTree = ""; }; + 1D7368D72C34FB07000EF904 /* RecipeDetailDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailDTO.swift; sourceTree = ""; }; + 1D7368D92C34FB14000EF904 /* RecipeDetailRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailRepository.swift; sourceTree = ""; }; + 1D7368DB2C34FB32000EF904 /* CustomNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; + 1D7368DF2C34FB38000EF904 /* RecipeDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailViewController.swift; sourceTree = ""; }; + 1D7368E02C34FB38000EF904 /* RecipeDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailView.swift; sourceTree = ""; }; + 1D7368E12C34FB38000EF904 /* RecipeDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailViewModel.swift; sourceTree = ""; }; + 1D7368E62C34FB66000EF904 /* RecipeDetailCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailCoordinator.swift; sourceTree = ""; }; + 1D7368E92C34FBF7000EF904 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = ""; }; + 1D95A0A32C37B0E200F09077 /* Fonts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = ""; }; + 1D95A0A72C37C7D400F09077 /* RecipeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeError.swift; sourceTree = ""; }; 1DE19E9C2C1B3DC10031804A /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 1DE19EA52C1B420A0031804A /* FeedListRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedListRepository.swift; sourceTree = ""; }; 1DE19EA62C1B420A0031804A /* SearchFeedListRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchFeedListRepository.swift; sourceTree = ""; }; 1DE19EB02C1B42200031804A /* NetworkService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = ""; }; - 1DE19EB42C1B422F0031804A /* RecipeItemViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeItemViewModel.swift; sourceTree = ""; }; - 1DE19EB62C1B422F0031804A /* RecipeDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailView.swift; sourceTree = ""; }; 1DE19EBA2C1B422F0031804A /* RecipeListItemViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeListItemViewModel.swift; sourceTree = ""; }; 1DE19EBB2C1B422F0031804A /* SearchBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = ""; }; 1DE19EBC2C1B422F0031804A /* RecipeListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeListViewController.swift; sourceTree = ""; }; @@ -135,10 +161,11 @@ 1D12839F2C15E7A700C5A870 /* Entities */ = { isa = PBXGroup; children = ( + 1D95A0A72C37C7D400F09077 /* RecipeError.swift */, 1D1283A12C15E94300C5A870 /* Recipe.swift */, + 1D7368C82C3443A1000EF904 /* Comment.swift */, + 1D7368C92C3443A1000EF904 /* User.swift */, 1D1283A32C15EA8100C5A870 /* RecipeType.swift */, - 1D1283A52C15EAA600C5A870 /* User.swift */, - 1D1283A72C15EABB00C5A870 /* Comment.swift */, ); path = Entities; sourceTree = ""; @@ -147,6 +174,7 @@ isa = PBXGroup; children = ( 1D1283A92C15EBCF00C5A870 /* SearchFeedUseCase.swift */, + 1D7368D12C34FADD000EF904 /* FetchRecipeDetailUseCase.swift */, 1D1283AB2C15EBE600C5A870 /* FetchFeedListUseCase.swift */, ); path = UseCases; @@ -173,19 +201,12 @@ children = ( 1D4741CB2C1B4F8D009381CE /* DTO */, 1D1283C92C16D9C600C5A870 /* RecipeFetchService.swift */, + 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */, 1DE19EB02C1B42200031804A /* NetworkService.swift */, ); path = Network; sourceTree = ""; }; - 1D1283C62C16CD9200C5A870 /* Utilities */ = { - isa = PBXGroup; - children = ( - 1D1283C72C16CE7C00C5A870 /* DateFormatter+Extensions.swift */, - ); - path = Utilities; - sourceTree = ""; - }; 1D2C16D92BE532B700C04508 = { isa = PBXGroup; children = ( @@ -211,8 +232,11 @@ 1D2C16E42BE532B700C04508 /* HomeCafeRecipes */ = { isa = PBXGroup; children = ( + 1D95A0A22C37B0E200F09077 /* Resources */, + 1D7368E52C34FB66000EF904 /* Coordinators */, + 1D7368CC2C344403000EF904 /* Utilities */, + 1D7368B42C3442C8000EF904 /* Extensions */, 1DE19EB22C1B422F0031804A /* Presentation */, - 1D1283C62C16CD9200C5A870 /* Utilities */, 1D1283AD2C16974B00C5A870 /* Data */, 1D740B402C15E6680001B704 /* Domain */, 1D2C16E52BE532B700C04508 /* AppDelegate.swift */, @@ -245,15 +269,67 @@ 1D4741CB2C1B4F8D009381CE /* DTO */ = { isa = PBXGroup; children = ( + 1D7368C62C344378000EF904 /* UserDTO.swift */, 1D4741CC2C1B4F8D009381CE /* RecipeImageDTO.swift */, 1D4741CD2C1B4F8D009381CE /* RecipeDTO.swift */, + 1D7368D72C34FB07000EF904 /* RecipeDetailDTO.swift */, 1D4741CE2C1B4F8D009381CE /* RecipePageDTO.swift */, 1D4741CF2C1B4F8D009381CE /* NetworkResponseDTO.swift */, - 1D4741D02C1B4F8D009381CE /* UserDTO.swift */, ); path = DTO; sourceTree = ""; }; + 1D7368B42C3442C8000EF904 /* Extensions */ = { + isa = PBXGroup; + children = ( + 1D7368B52C3442C8000EF904 /* String+Validation.swift */, + 1D7368B62C3442C8000EF904 /* UIImageViewImageLoading.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 1D7368CC2C344403000EF904 /* Utilities */ = { + isa = PBXGroup; + children = ( + 1D7368CD2C344403000EF904 /* DateFormatter+Extensions.swift */, + ); + path = Utilities; + sourceTree = ""; + }; + 1D7368DD2C34FB38000EF904 /* Feed */ = { + isa = PBXGroup; + children = ( + 1D7368DE2C34FB38000EF904 /* View */, + 1D7368E12C34FB38000EF904 /* RecipeDetailViewModel.swift */, + ); + path = Feed; + sourceTree = ""; + }; + 1D7368DE2C34FB38000EF904 /* View */ = { + isa = PBXGroup; + children = ( + 1D7368DF2C34FB38000EF904 /* RecipeDetailViewController.swift */, + 1D7368E02C34FB38000EF904 /* RecipeDetailView.swift */, + ); + path = View; + sourceTree = ""; + }; + 1D7368E52C34FB66000EF904 /* Coordinators */ = { + isa = PBXGroup; + children = ( + 1D7368E62C34FB66000EF904 /* RecipeDetailCoordinator.swift */, + ); + path = Coordinators; + sourceTree = ""; + }; + 1D7368E82C34FBF7000EF904 /* Tabbar */ = { + isa = PBXGroup; + children = ( + 1D7368E92C34FBF7000EF904 /* MainTabBarController.swift */, + ); + path = Tabbar; + sourceTree = ""; + }; 1D740B402C15E6680001B704 /* Domain */ = { isa = PBXGroup; children = ( @@ -264,10 +340,18 @@ path = Domain; sourceTree = ""; }; + 1D95A0A22C37B0E200F09077 /* Resources */ = { + isa = PBXGroup; + children = ( + 1D95A0A32C37B0E200F09077 /* Fonts.swift */, + ); + path = Resources; + sourceTree = ""; + }; 1DDFFD822C1C09AB0083B077 /* Mapper */ = { isa = PBXGroup; children = ( - 1DDFFD802C1C096A0083B077 /* RecipeMapper.swift */, + 1D7368B92C3442DE000EF904 /* RecipeListMapper.swift */, ); path = Mapper; sourceTree = ""; @@ -276,6 +360,7 @@ isa = PBXGroup; children = ( 1DE19EA52C1B420A0031804A /* FeedListRepository.swift */, + 1D7368D92C34FB14000EF904 /* RecipeDetailRepository.swift */, 1DE19EA62C1B420A0031804A /* SearchFeedListRepository.swift */, ); path = Repositories; @@ -284,30 +369,15 @@ 1DE19EB22C1B422F0031804A /* Presentation */ = { isa = PBXGroup; children = ( + 1D7368E82C34FBF7000EF904 /* Tabbar */, + 1D7368DD2C34FB38000EF904 /* Feed */, + 1D7368DB2C34FB32000EF904 /* CustomNavigationBar.swift */, 1DDFFD822C1C09AB0083B077 /* Mapper */, - 1DE19EB32C1B422F0031804A /* Feed */, 1DE19EB72C1B422F0031804A /* FeedList */, ); path = Presentation; sourceTree = ""; }; - 1DE19EB32C1B422F0031804A /* Feed */ = { - isa = PBXGroup; - children = ( - 1DE19EB42C1B422F0031804A /* RecipeItemViewModel.swift */, - 1DE19EB52C1B422F0031804A /* View */, - ); - path = Feed; - sourceTree = ""; - }; - 1DE19EB52C1B422F0031804A /* View */ = { - isa = PBXGroup; - children = ( - 1DE19EB62C1B422F0031804A /* RecipeDetailView.swift */, - ); - path = View; - sourceTree = ""; - }; 1DE19EB72C1B422F0031804A /* FeedList */ = { isa = PBXGroup; children = ( @@ -331,6 +401,7 @@ 1DF829AF2C299F1F00C337FC /* Interactor */ = { isa = PBXGroup; children = ( + 1D7368D32C34FAE8000EF904 /* RecipeDetailInteractor.swift */, 1DF829B02C299F1F00C337FC /* RecipeListInteractor.swift */, ); path = Interactor; @@ -479,32 +550,45 @@ files = ( 1DF829B12C299F1F00C337FC /* RecipeListInteractor.swift in Sources */, 1D2C16EA2BE532B700C04508 /* ViewController.swift in Sources */, + 1D7368EA2C34FBF7000EF904 /* MainTabBarController.swift in Sources */, + 1D7368D42C34FAE8000EF904 /* RecipeDetailInteractor.swift in Sources */, 1DE19EC52C1B422F0031804A /* RecipeListView.swift in Sources */, + 1D7368CB2C3443A1000EF904 /* User.swift in Sources */, 1D4741D32C1B4F8D009381CE /* RecipePageDTO.swift in Sources */, + 1D7368CE2C344403000EF904 /* DateFormatter+Extensions.swift in Sources */, + 1D7368E32C34FB38000EF904 /* RecipeDetailView.swift in Sources */, 1D2C16E62BE532B700C04508 /* AppDelegate.swift in Sources */, 1DE19EB12C1B42200031804A /* NetworkService.swift in Sources */, - 1D1283A62C15EAA600C5A870 /* User.swift in Sources */, 1D1283AC2C15EBE600C5A870 /* FetchFeedListUseCase.swift in Sources */, - 1D1283A82C15EABB00C5A870 /* Comment.swift in Sources */, - 1D1283C82C16CE7C00C5A870 /* DateFormatter+Extensions.swift in Sources */, + 1D7368E22C34FB38000EF904 /* RecipeDetailViewController.swift in Sources */, 1D1283A42C15EA8100C5A870 /* RecipeType.swift in Sources */, + 1D7368D82C34FB07000EF904 /* RecipeDetailDTO.swift in Sources */, + 1D7368DA2C34FB14000EF904 /* RecipeDetailRepository.swift in Sources */, 1D4741D22C1B4F8D009381CE /* RecipeDTO.swift in Sources */, - 1DE19EC02C1B422F0031804A /* RecipeDetailView.swift in Sources */, 1D1283AA2C15EBCF00C5A870 /* SearchFeedUseCase.swift in Sources */, 1DE19EA82C1B420A0031804A /* SearchFeedListRepository.swift in Sources */, - 1D4741D52C1B4F8D009381CE /* UserDTO.swift in Sources */, + 1D95A0A42C37B0E200F09077 /* Fonts.swift in Sources */, 1DE19EC22C1B422F0031804A /* RecipeListItemViewModel.swift in Sources */, + 1D7368C72C344378000EF904 /* UserDTO.swift in Sources */, 1DE19EC32C1B422F0031804A /* SearchBar.swift in Sources */, 1DE19E9D2C1B3DC10031804A /* SceneDelegate.swift in Sources */, 1D4741D12C1B4F8D009381CE /* RecipeImageDTO.swift in Sources */, 1DE19EA72C1B420A0031804A /* FeedListRepository.swift in Sources */, 1DE19EC62C1B422F0031804A /* RecipeListCell.swift in Sources */, - 1DDFFD812C1C096A0083B077 /* RecipeMapper.swift in Sources */, + 1D7368E72C34FB66000EF904 /* RecipeDetailCoordinator.swift in Sources */, + 1D7368D22C34FADD000EF904 /* FetchRecipeDetailUseCase.swift in Sources */, 1DE19EC42C1B422F0031804A /* RecipeListViewController.swift in Sources */, - 1DE19EBF2C1B422F0031804A /* RecipeItemViewModel.swift in Sources */, + 1D7368D62C34FAF9000EF904 /* RecipeDetailFetchService.swift in Sources */, + 1D95A0A82C37C7D400F09077 /* RecipeError.swift in Sources */, 1D1283A22C15E94300C5A870 /* Recipe.swift in Sources */, + 1D7368BA2C3442DE000EF904 /* RecipeListMapper.swift in Sources */, + 1D7368CA2C3443A1000EF904 /* Comment.swift in Sources */, 1D1283CA2C16D9C600C5A870 /* RecipeFetchService.swift in Sources */, + 1D7368E42C34FB38000EF904 /* RecipeDetailViewModel.swift in Sources */, + 1D7368B82C3442C8000EF904 /* UIImageViewImageLoading.swift in Sources */, 1D4741D42C1B4F8D009381CE /* NetworkResponseDTO.swift in Sources */, + 1D7368B72C3442C8000EF904 /* String+Validation.swift in Sources */, + 1D7368DC2C34FB32000EF904 /* CustomNavigationBar.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift index e3f1ec7..d1e0321 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift @@ -26,15 +26,15 @@ final class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { func fetchRecipeDetail(recipeID: Int) -> Single { guard let url = makeURL(recipeID: recipeID) else { - return Single.error(RecipeError.invalidURL) + return Single.error(RecipeDetailError.invalidURL) } return networkService.getRequest(url: url, responseType: NetworkResponseDTO.self) .map { $0.data.toDomain() } .catch { error in guard let decodingError = error as? DecodingError else { - return Single.error(RecipeError.networkError(error)) + return Single.error(RecipeDetailError.networkError(error)) } - return Single.error(RecipeError.decodingError) + return Single.error(RecipeDetailError.decodingError) } } } diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeDetailError.swift similarity index 88% rename from HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift rename to HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeDetailError.swift index fbb4c94..8070905 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeError.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/Entities/RecipeDetailError.swift @@ -7,14 +7,14 @@ import Foundation -enum RecipeError: Error { +enum RecipeDetailError: Error { case invalidURL case networkError(Error) case decodingError case unknownError } -extension RecipeError: LocalizedError { +extension RecipeDetailError: LocalizedError { var errorDescription: String? { switch self { case .invalidURL: From cda676a347196958713527f2c0e14e82f008ea47 Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Tue, 9 Jul 2024 16:32:14 +0900 Subject: [PATCH 12/13] =?UTF-8?q?Fix:=20RecipeDetailFetchService=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=ED=9B=84=20Repository=EC=97=90=20Service=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeCafeRecipes.xcodeproj/project.pbxproj | 12 ++---- .../Network/RecipeDetailFetchService.swift | 40 ------------------- .../Repositories/RecipeDetailRepository.swift | 25 ++++++++++-- 3 files changed, 25 insertions(+), 52 deletions(-) delete mode 100644 HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj index c0ef8ae..13a9dbd 100644 --- a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj +++ b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj @@ -34,7 +34,6 @@ 1D7368CE2C344403000EF904 /* DateFormatter+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368CD2C344403000EF904 /* DateFormatter+Extensions.swift */; }; 1D7368D22C34FADD000EF904 /* FetchRecipeDetailUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D12C34FADD000EF904 /* FetchRecipeDetailUseCase.swift */; }; 1D7368D42C34FAE8000EF904 /* RecipeDetailInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D32C34FAE8000EF904 /* RecipeDetailInteractor.swift */; }; - 1D7368D62C34FAF9000EF904 /* RecipeDetailFetchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */; }; 1D7368D82C34FB07000EF904 /* RecipeDetailDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D72C34FB07000EF904 /* RecipeDetailDTO.swift */; }; 1D7368DA2C34FB14000EF904 /* RecipeDetailRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368D92C34FB14000EF904 /* RecipeDetailRepository.swift */; }; 1D7368DC2C34FB32000EF904 /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368DB2C34FB32000EF904 /* CustomNavigationBar.swift */; }; @@ -44,7 +43,7 @@ 1D7368E72C34FB66000EF904 /* RecipeDetailCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E62C34FB66000EF904 /* RecipeDetailCoordinator.swift */; }; 1D7368EA2C34FBF7000EF904 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368E92C34FBF7000EF904 /* MainTabBarController.swift */; }; 1D95A0A42C37B0E200F09077 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D95A0A32C37B0E200F09077 /* Fonts.swift */; }; - 1D95A0A82C37C7D400F09077 /* RecipeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D95A0A72C37C7D400F09077 /* RecipeError.swift */; }; + 1D95A0A82C37C7D400F09077 /* RecipeDetailError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D95A0A72C37C7D400F09077 /* RecipeDetailError.swift */; }; 1DE19E9D2C1B3DC10031804A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19E9C2C1B3DC10031804A /* SceneDelegate.swift */; }; 1DE19EA72C1B420A0031804A /* FeedListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EA52C1B420A0031804A /* FeedListRepository.swift */; }; 1DE19EA82C1B420A0031804A /* SearchFeedListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE19EA62C1B420A0031804A /* SearchFeedListRepository.swift */; }; @@ -105,7 +104,6 @@ 1D7368CD2C344403000EF904 /* DateFormatter+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormatter+Extensions.swift"; sourceTree = ""; }; 1D7368D12C34FADD000EF904 /* FetchRecipeDetailUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchRecipeDetailUseCase.swift; sourceTree = ""; }; 1D7368D32C34FAE8000EF904 /* RecipeDetailInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailInteractor.swift; sourceTree = ""; }; - 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailFetchService.swift; sourceTree = ""; }; 1D7368D72C34FB07000EF904 /* RecipeDetailDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailDTO.swift; sourceTree = ""; }; 1D7368D92C34FB14000EF904 /* RecipeDetailRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailRepository.swift; sourceTree = ""; }; 1D7368DB2C34FB32000EF904 /* CustomNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = ""; }; @@ -115,7 +113,7 @@ 1D7368E62C34FB66000EF904 /* RecipeDetailCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailCoordinator.swift; sourceTree = ""; }; 1D7368E92C34FBF7000EF904 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = ""; }; 1D95A0A32C37B0E200F09077 /* Fonts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = ""; }; - 1D95A0A72C37C7D400F09077 /* RecipeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeError.swift; sourceTree = ""; }; + 1D95A0A72C37C7D400F09077 /* RecipeDetailError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDetailError.swift; sourceTree = ""; }; 1DE19E9C2C1B3DC10031804A /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 1DE19EA52C1B420A0031804A /* FeedListRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedListRepository.swift; sourceTree = ""; }; 1DE19EA62C1B420A0031804A /* SearchFeedListRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchFeedListRepository.swift; sourceTree = ""; }; @@ -161,7 +159,7 @@ 1D12839F2C15E7A700C5A870 /* Entities */ = { isa = PBXGroup; children = ( - 1D95A0A72C37C7D400F09077 /* RecipeError.swift */, + 1D95A0A72C37C7D400F09077 /* RecipeDetailError.swift */, 1D1283A12C15E94300C5A870 /* Recipe.swift */, 1D7368C82C3443A1000EF904 /* Comment.swift */, 1D7368C92C3443A1000EF904 /* User.swift */, @@ -201,7 +199,6 @@ children = ( 1D4741CB2C1B4F8D009381CE /* DTO */, 1D1283C92C16D9C600C5A870 /* RecipeFetchService.swift */, - 1D7368D52C34FAF9000EF904 /* RecipeDetailFetchService.swift */, 1DE19EB02C1B42200031804A /* NetworkService.swift */, ); path = Network; @@ -578,8 +575,7 @@ 1D7368E72C34FB66000EF904 /* RecipeDetailCoordinator.swift in Sources */, 1D7368D22C34FADD000EF904 /* FetchRecipeDetailUseCase.swift in Sources */, 1DE19EC42C1B422F0031804A /* RecipeListViewController.swift in Sources */, - 1D7368D62C34FAF9000EF904 /* RecipeDetailFetchService.swift in Sources */, - 1D95A0A82C37C7D400F09077 /* RecipeError.swift in Sources */, + 1D95A0A82C37C7D400F09077 /* RecipeDetailError.swift in Sources */, 1D1283A22C15E94300C5A870 /* Recipe.swift in Sources */, 1D7368BA2C3442DE000EF904 /* RecipeListMapper.swift in Sources */, 1D7368CA2C3443A1000EF904 /* Comment.swift in Sources */, diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift deleted file mode 100644 index d1e0321..0000000 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeDetailFetchService.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// RecipeDetailFetchService.swift -// HomeCafeRecipes -// -// Created by 김건호 on 6/26/24. -// - -import Foundation -import RxSwift - -protocol RecipeDetailFetchService { - func fetchRecipeDetail(recipeID: Int) -> Single -} - -final class RecipeDetailFetchServiceImpl: RecipeDetailFetchService { - private let networkService: NetworkService - private static let baseURL: URL = URL(string: "https://meog0.store/api")! - - init(networkService: NetworkService) { - self.networkService = networkService - } - - private func makeURL(recipeID: Int) -> URL? { - return RecipeDetailFetchServiceImpl.baseURL.appendingPathComponent("recipes/\(recipeID)") - } - - func fetchRecipeDetail(recipeID: Int) -> Single { - guard let url = makeURL(recipeID: recipeID) else { - return Single.error(RecipeDetailError.invalidURL) - } - return networkService.getRequest(url: url, responseType: NetworkResponseDTO.self) - .map { $0.data.toDomain() } - .catch { error in - guard let decodingError = error as? DecodingError else { - return Single.error(RecipeDetailError.networkError(error)) - } - return Single.error(RecipeDetailError.decodingError) - } - } -} diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift index a8ea888..83862ce 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift @@ -6,20 +6,37 @@ // import Foundation + import RxSwift protocol RecipeDetailRepository { func fetchRecipeDetail(recipeID: Int) -> Single } -class FeedListRepositoryImpl: RecipeDetailRepository { - private let networkService: RecipeDetailFetchService +class RecipeDetailRepositoryImpl: RecipeDetailRepository { + private let networkService: NetworkService + private static let baseURL: URL = URL(string: "https://meog0.store/api")! - init(networkService: RecipeDetailFetchService) { + init(networkService: NetworkService) { self.networkService = networkService } + private func makeURL(recipeId: Int) -> URL? { + return RecipeDetailRepositoryImpl.baseURL.appendingPathComponent("recipes/\(recipeId)") + } + func fetchRecipeDetail(recipeID: Int) -> Single { - return networkService.fetchRecipeDetail(recipeID: recipeID) + guard let URL = makeURL(recipeId: recipeID) else { + return Single.error(RecipeDetailError.invalidURL) + } + return networkService.getRequest(url: URL, responseType: NetworkResponseDTO.self) + .map { $0.data.toDomain() } + .catch { error in + if let decodingError = error as? DecodingError { + return Single.error(RecipeDetailError.decodingError) + } else { + return Single.error(RecipeDetailError.networkError(error)) + } + } } } From dbf21111eee3742972925692cd2e554fb8541adf Mon Sep 17 00:00:00 2001 From: GeonH0 Date: Wed, 10 Jul 2024 13:52:02 +0900 Subject: [PATCH 13/13] =?UTF-8?q?Fix:=20APIConfig=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=9B=84=20=EA=B0=81=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=EC=97=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeCafeRecipes.xcodeproj/project.pbxproj | 6 ++++++ .../HomeCafeRecipes/Data/Network/APIConfig.swift | 12 ++++++++++++ .../Data/Network/NetworkService.swift | 1 - .../Data/Network/RecipeFetchService.swift | 5 ++--- .../Data/Repositories/FeedListRepository.swift | 2 +- .../Data/Repositories/RecipeDetailRepository.swift | 3 +-- .../Data/Repositories/SearchFeedListRepository.swift | 2 +- .../Domain/UseCases/FetchFeedListUseCase.swift | 2 +- .../Domain/UseCases/SearchFeedUseCase.swift | 2 +- 9 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 HomeCafeRecipes/HomeCafeRecipes/Data/Network/APIConfig.swift diff --git a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj index 13a9dbd..a6a3d11 100644 --- a/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj +++ b/HomeCafeRecipes/HomeCafeRecipes.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ 1D4741D22C1B4F8D009381CE /* RecipeDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CD2C1B4F8D009381CE /* RecipeDTO.swift */; }; 1D4741D32C1B4F8D009381CE /* RecipePageDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CE2C1B4F8D009381CE /* RecipePageDTO.swift */; }; 1D4741D42C1B4F8D009381CE /* NetworkResponseDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D4741CF2C1B4F8D009381CE /* NetworkResponseDTO.swift */; }; + 1D60CC452C3F932D00D08FA3 /* APIConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D60CC442C3F932D00D08FA3 /* APIConfig.swift */; }; + 1D60CC462C3F932D00D08FA3 /* APIConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D60CC442C3F932D00D08FA3 /* APIConfig.swift */; }; 1D7368B72C3442C8000EF904 /* String+Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B52C3442C8000EF904 /* String+Validation.swift */; }; 1D7368B82C3442C8000EF904 /* UIImageViewImageLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B62C3442C8000EF904 /* UIImageViewImageLoading.swift */; }; 1D7368BA2C3442DE000EF904 /* RecipeListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7368B92C3442DE000EF904 /* RecipeListMapper.swift */; }; @@ -95,6 +97,7 @@ 1D4741CD2C1B4F8D009381CE /* RecipeDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeDTO.swift; sourceTree = ""; }; 1D4741CE2C1B4F8D009381CE /* RecipePageDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipePageDTO.swift; sourceTree = ""; }; 1D4741CF2C1B4F8D009381CE /* NetworkResponseDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkResponseDTO.swift; sourceTree = ""; }; + 1D60CC442C3F932D00D08FA3 /* APIConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIConfig.swift; sourceTree = ""; }; 1D7368B52C3442C8000EF904 /* String+Validation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Validation.swift"; sourceTree = ""; }; 1D7368B62C3442C8000EF904 /* UIImageViewImageLoading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageViewImageLoading.swift; sourceTree = ""; }; 1D7368B92C3442DE000EF904 /* RecipeListMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipeListMapper.swift; sourceTree = ""; }; @@ -200,6 +203,7 @@ 1D4741CB2C1B4F8D009381CE /* DTO */, 1D1283C92C16D9C600C5A870 /* RecipeFetchService.swift */, 1DE19EB02C1B42200031804A /* NetworkService.swift */, + 1D60CC442C3F932D00D08FA3 /* APIConfig.swift */, ); path = Network; sourceTree = ""; @@ -548,6 +552,7 @@ 1DF829B12C299F1F00C337FC /* RecipeListInteractor.swift in Sources */, 1D2C16EA2BE532B700C04508 /* ViewController.swift in Sources */, 1D7368EA2C34FBF7000EF904 /* MainTabBarController.swift in Sources */, + 1D60CC452C3F932D00D08FA3 /* APIConfig.swift in Sources */, 1D7368D42C34FAE8000EF904 /* RecipeDetailInteractor.swift in Sources */, 1DE19EC52C1B422F0031804A /* RecipeListView.swift in Sources */, 1D7368CB2C3443A1000EF904 /* User.swift in Sources */, @@ -592,6 +597,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1D60CC462C3F932D00D08FA3 /* APIConfig.swift in Sources */, 1D2C16FD2BE532B800C04508 /* HomeCafeRecipesTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/APIConfig.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/APIConfig.swift new file mode 100644 index 0000000..076d13c --- /dev/null +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/APIConfig.swift @@ -0,0 +1,12 @@ +// +// BaseURL.swift +// HomeCafeRecipes +// +// Created by 김건호 on 7/10/24. +// + +import Foundation + +struct APIConfig { + let baseURL = URL(string: "https://meog0.store/api")! +} diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/NetworkService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/NetworkService.swift index cba7705..0e17774 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/NetworkService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/NetworkService.swift @@ -13,7 +13,6 @@ protocol NetworkService { } class BaseNetworkService: NetworkService { - let baseURL = URL(string: "https://meog0.store/api")! func getRequest(url: URL, responseType: T.Type) -> Single { var request = URLRequest(url: url) diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift index 135c541..628b0ea 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Network/RecipeFetchService.swift @@ -13,16 +13,15 @@ protocol RecipeFetchService { func searchRecipes(title: String, pageNumber: Int) -> Single<[Recipe]> } -class DefaultRecipeFetchService: RecipeFetchService { +class RecipeFetchServiceImpl: RecipeFetchService { private let networkService: NetworkService - private static let baseURL: URL = URL(string: "https://meog0.store/api")! init(networkService: NetworkService) { self.networkService = networkService } private func makeURL(endpoint: String, queryItems: [URLQueryItem]) -> URL? { - let URL = DefaultRecipeFetchService.baseURL.appendingPathComponent(endpoint) + let URL = APIConfig().baseURL.appendingPathComponent(endpoint) var URLComponents = URLComponents(url: URL, resolvingAgainstBaseURL: false) URLComponents?.queryItems = queryItems return URLComponents?.url diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift index 2fda774..21be892 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/FeedListRepository.swift @@ -11,7 +11,7 @@ protocol FeedListRepository { func fetchRecipes(pageNumber: Int) -> Single<[Recipe]> } -class DefaultFeedListRepository: FeedListRepository { +class FeedListRepositoryImpl: FeedListRepository { private let networkService: RecipeFetchService init(networkService: RecipeFetchService) { diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift index 83862ce..25af022 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/RecipeDetailRepository.swift @@ -15,14 +15,13 @@ protocol RecipeDetailRepository { class RecipeDetailRepositoryImpl: RecipeDetailRepository { private let networkService: NetworkService - private static let baseURL: URL = URL(string: "https://meog0.store/api")! init(networkService: NetworkService) { self.networkService = networkService } private func makeURL(recipeId: Int) -> URL? { - return RecipeDetailRepositoryImpl.baseURL.appendingPathComponent("recipes/\(recipeId)") + return APIConfig().baseURL.appendingPathComponent("recipes/\(recipeId)") } func fetchRecipeDetail(recipeID: Int) -> Single { diff --git a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/SearchFeedListRepository.swift b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/SearchFeedListRepository.swift index 6b4b21d..027cf74 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/SearchFeedListRepository.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Data/Repositories/SearchFeedListRepository.swift @@ -11,7 +11,7 @@ protocol SearchFeedListRepository { func searchRecipes(title: String, pageNumber: Int) -> Single<[Recipe]> } -class DefaultSearchFeedRepository: SearchFeedListRepository { +class SearchFeedRepositoryImpl: SearchFeedListRepository { private let networkService: RecipeFetchService diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift index f5b4152..35a96e1 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/FetchFeedListUseCase.swift @@ -11,7 +11,7 @@ protocol FetchFeedListUseCase { func execute(pageNumber: Int) -> Single> } -class DefaultFetchFeedListUseCase: FetchFeedListUseCase { +class FetchFeedListUseCaseImpl: FetchFeedListUseCase { private let repository: FeedListRepository init(repository: FeedListRepository) { diff --git a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/SearchFeedUseCase.swift b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/SearchFeedUseCase.swift index 68fd1c3..f65e639 100644 --- a/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/SearchFeedUseCase.swift +++ b/HomeCafeRecipes/HomeCafeRecipes/Domain/UseCases/SearchFeedUseCase.swift @@ -11,7 +11,7 @@ protocol SearchFeedListUseCase { func execute(title: String,pageNumber: Int) -> Single> } -class DefaultSearchFeedListUseCase: SearchFeedListUseCase { +class SearchFeedListUseCaseImpl: SearchFeedListUseCase { private let repository: SearchFeedListRepository init(repository: SearchFeedListRepository) {