-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
π SearchViewModel ꡬν λ° μ°κ΄λ κΈ°λ₯ ꡬν (#78)
* β¨ SearchViewModel ꡬν * π₯ λΆνμν μ½λ μμ * β¨ SearchViewComponent ꡬν * β¨ HomeView μ΄λμ λΌμ΄μ μμ λ° viewModel μμ± μΆκ°
- Loading branch information
Showing
6 changed files
with
166 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
PyeonHaeng-iOS/Sources/Scenes/ProductSearchScene/SearchViewComponent.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// | ||
// SearchViewComponent.swift | ||
// PyeonHaeng-iOS | ||
// | ||
// Created by κΉμμ² on 3/4/24. | ||
// | ||
|
||
import Foundation | ||
import Network | ||
import SearchAPI | ||
import SearchAPISupport | ||
|
||
// MARK: - SearchDependency | ||
|
||
protocol SearchDependency { | ||
var searchService: SearchServiceRepresentable { get } | ||
} | ||
|
||
// MARK: - SearchViewComponent | ||
|
||
struct SearchViewComponent: SearchDependency { | ||
let searchService: SearchServiceRepresentable | ||
|
||
init() { | ||
let searchNetworking: Networking = { | ||
let configuration: URLSessionConfiguration | ||
#if DEBUG | ||
configuration = .ephemeral | ||
configuration.protocolClasses = [SearchURLProtocol.self] | ||
#else | ||
configuration = .default | ||
#endif | ||
let provider = NetworkProvider(session: URLSession(configuration: configuration)) | ||
return provider | ||
}() | ||
|
||
searchService = SearchService(network: searchNetworking) | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
PyeonHaeng-iOS/Sources/Scenes/ProductSearchScene/SearchViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// | ||
// SearchViewModel.swift | ||
// PyeonHaeng-iOS | ||
// | ||
// Created by κΉμμ² on 3/3/24. | ||
// | ||
|
||
import Entity | ||
import Foundation | ||
import Log | ||
import SearchAPI | ||
|
||
// MARK: - SearchAction | ||
|
||
enum SearchAction { | ||
case textChanged(String) | ||
case loadMoreProducts | ||
} | ||
|
||
// MARK: - SearchState | ||
|
||
struct SearchState { | ||
var currentText = "" | ||
var products = [SearchProduct]() | ||
var offset = 0 | ||
var hasMore = false | ||
|
||
/// νλ©΄ μ€μμ νμλλ λ‘λ© μΈλμΌμ΄ν° | ||
var isLoading = false | ||
/// 리μ€νΈ 맨 νλ¨μ νμλλ λ‘λ© μΈλμΌμ΄ν° | ||
var isMoreLoading = false | ||
} | ||
|
||
// MARK: - SearchViewModelRepresentable | ||
|
||
protocol SearchViewModelRepresentable: ObservableObject { | ||
var state: SearchState { get } | ||
func trigger(_ action: SearchAction) | ||
} | ||
|
||
// MARK: - SearchViewModel | ||
|
||
final class SearchViewModel: SearchViewModelRepresentable { | ||
/// λΉλκΈ° ν¨μλ₯Ό μ€νν©λλ€. λ§μ½ μ€λ₯κ° λ°μνλ©΄ Logλ‘ κ°μ νμΈν μ μμ΅λλ€. | ||
func performAsyncAction(_ action: () async throws -> Void) async { | ||
do { | ||
try await action() | ||
} catch { | ||
Log.make(with: .viewModel)?.error("\(String(describing: error))") | ||
} | ||
} | ||
|
||
private let service: SearchServiceRepresentable | ||
|
||
@Published private(set) var state: SearchState = .init() | ||
|
||
init(service: SearchServiceRepresentable) { | ||
self.service = service | ||
} | ||
|
||
func trigger(_ action: SearchAction) { | ||
Task { | ||
await handle(action) | ||
} | ||
} | ||
|
||
private func handle(_ action: SearchAction) async { | ||
// λΉλκΈ° ν¨μλ₯Ό μ€νν©λλ€. λ§μ½ μ€λ₯κ° λ°μνλ©΄ Logλ‘ κ°μ νμΈν μ μμ΅λλ€. | ||
func performAsyncAction(_ action: () async throws -> Void) async { | ||
do { | ||
try await action() | ||
} catch { | ||
Log.make(with: .viewModel)?.error("\(String(describing: error))") | ||
} | ||
} | ||
|
||
switch action { | ||
case let .textChanged(text): | ||
state.currentText = text | ||
state.offset = 0 | ||
await performAsyncAction { | ||
try await fetchSearchList(isReplace: true) | ||
} | ||
|
||
case .loadMoreProducts: | ||
await performAsyncAction { | ||
try await fetchSearchList(isReplace: false) | ||
} | ||
} | ||
} | ||
|
||
private func fetchSearchList(isReplace: Bool) async throws { | ||
let request = SearchProductRequest( | ||
name: state.currentText, | ||
order: .normal, | ||
pageSize: 20, | ||
offset: state.offset | ||
) | ||
|
||
let paginatedModel = try await service.fetchSearchList(request: request) | ||
|
||
state.hasMore = paginatedModel.hasMore | ||
state.offset += 1 | ||
if isReplace { | ||
state.products = paginatedModel.results | ||
} else { | ||
state.products.append(contentsOf: paginatedModel.results) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters