From c72452df3fa1281761f5a8f1c58ea12a3647cd1b Mon Sep 17 00:00:00 2001 From: RomanPodymov Date: Wed, 19 Mar 2025 17:03:47 +0100 Subject: [PATCH 01/14] Testing --- BookieTests/BookieTests.swift | 8 +++++--- project.yml | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/BookieTests/BookieTests.swift b/BookieTests/BookieTests.swift index cb5af79..f104123 100644 --- a/BookieTests/BookieTests.swift +++ b/BookieTests/BookieTests.swift @@ -7,12 +7,14 @@ // @testable import BookieApp -import XCTest +import Testing -class BookieTests: XCTestCase { +@Suite +struct BookieTests { + @Test func testAsyncMap() async { let mappedValue = await (10 as Int?).mapAsync(someAsyncFunc) - XCTAssertEqual(mappedValue, 100) + #expect(mappedValue == 101) } private func someAsyncFunc(previousValue: Int) async -> Int { diff --git a/project.yml b/project.yml index a6301c0..75ebf86 100644 --- a/project.yml +++ b/project.yml @@ -81,6 +81,10 @@ targets: - script: "mint run swiftlint" name: SwiftLint BookieAppTests: + settings: + base: + SWIFT_VERSION: 6 + SWIFT_ACTIVE_COMPILATION_CONDITIONS: ${SWIFT_ACTIVE_COMPILATION_CONDITIONS} type: bundle.unit-test platform: iOS sources: [BookieTests] From ee780e33d33aa3acc4b698763132a032b9f5cde0 Mon Sep 17 00:00:00 2001 From: RomanPodymov Date: Thu, 20 Mar 2025 12:09:20 +0100 Subject: [PATCH 02/14] Using Kit --- Bookie/UI/BooksViewModel.swift | 13 ++++++------- project.yml | 3 +++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Bookie/UI/BooksViewModel.swift b/Bookie/UI/BooksViewModel.swift index d0bb484..038faa9 100644 --- a/Bookie/UI/BooksViewModel.swift +++ b/Bookie/UI/BooksViewModel.swift @@ -10,10 +10,11 @@ import Combine import CombineMoya import DifferenceKit import Foundation +import JobInterviewAssignmentKit import Moya import OrderedCollections -protocol AnyBooksScreen: AnyObject, Sendable { +protocol AnyBooksScreen: AnyScreen, Sendable { func onNewDataReceived(oldSet: DataSetType, newSet: DataSetType) async func onNewDataError(_ error: BooksViewModelError) async func onSearchTextChanged(_ searchText: String) async @@ -38,9 +39,7 @@ enum BooksViewModelError: Error { case requestError(Error) } -final class BooksViewModel { - unowned var screen: AnyBooksScreen! - +final class BooksViewModel: AnyViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -51,8 +50,8 @@ final class BooksViewModel { private var cancellables = Set() init(screen: AnyBooksScreen!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { - self.screen = screen self.searchText = .init(searchText) + super.init(screen: screen) self.previousBook = previousBook self.data = data self.searchText.removeDuplicates().sink { [weak screen] text in @@ -85,9 +84,9 @@ final class BooksViewModel { lhs.model.joined() < rhs.model.joined() } - await screen?.onNewDataReceived(oldSet: oldSet, newSet: newSet) + await (screen as? AnyBooksScreen)?.onNewDataReceived(oldSet: oldSet, newSet: newSet) } catch { - await screen?.onNewDataError(error) + await (screen as? AnyBooksScreen)?.onNewDataError(error) } } diff --git a/project.yml b/project.yml index 75ebf86..68ac5f9 100644 --- a/project.yml +++ b/project.yml @@ -44,6 +44,8 @@ packages: OrderedCollections: url: https://github.com/apple/swift-collections version: 1.1.4 + JobInterviewAssignmentKit: + path: ../JobInterviewAssignmentKit targets: BookieApp: settings: @@ -67,6 +69,7 @@ targets: - package: UICollectionViewLeftAlignedLayout - package: SwiftAlertView - package: OrderedCollections + - package: JobInterviewAssignmentKit info: path: Bookie/Info.plist properties: From 3043a4edcbae89123aec15732b7d8f82ba5b2f7d Mon Sep 17 00:00:00 2001 From: RomanPodymov Date: Thu, 20 Mar 2025 12:17:04 +0100 Subject: [PATCH 03/14] BookScreen with new Kit --- Bookie/UI/BookViewModel.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Bookie/UI/BookViewModel.swift b/Bookie/UI/BookViewModel.swift index 443d575..a96e682 100644 --- a/Bookie/UI/BookViewModel.swift +++ b/Bookie/UI/BookViewModel.swift @@ -6,17 +6,16 @@ // Copyright © 2025 Bookie. All rights reserved. // +import JobInterviewAssignmentKit import UIKit -protocol AnyBookScreen: AnyObject {} - -class BookViewModel { - unowned var screen: AnyBookScreen! +protocol AnyBookScreen: AnyScreen {} +final class BookViewModel: AnyViewModel { var data: Book? init(screen: AnyBookScreen!, data: Book? = nil) { - self.screen = screen + super.init(screen: screen) self.data = data } From 852f1f1bfbeb7cdcc3ccc8ad8179456f399d794d Mon Sep 17 00:00:00 2001 From: RomanPodymov Date: Tue, 15 Apr 2025 11:43:13 +0200 Subject: [PATCH 04/14] Generics --- Bookie/UI/BookViewModel.swift | 4 ++-- Bookie/UI/BooksViewModel.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Bookie/UI/BookViewModel.swift b/Bookie/UI/BookViewModel.swift index a96e682..048bdb4 100644 --- a/Bookie/UI/BookViewModel.swift +++ b/Bookie/UI/BookViewModel.swift @@ -11,10 +11,10 @@ import UIKit protocol AnyBookScreen: AnyScreen {} -final class BookViewModel: AnyViewModel { +final class BookViewModel: AnyViewModel { var data: Book? - init(screen: AnyBookScreen!, data: Book? = nil) { + init(screen: BookScreen!, data: Book? = nil) { super.init(screen: screen) self.data = data } diff --git a/Bookie/UI/BooksViewModel.swift b/Bookie/UI/BooksViewModel.swift index 038faa9..e8aee4d 100644 --- a/Bookie/UI/BooksViewModel.swift +++ b/Bookie/UI/BooksViewModel.swift @@ -39,7 +39,7 @@ enum BooksViewModelError: Error { case requestError(Error) } -final class BooksViewModel: AnyViewModel { +final class BooksViewModel: AnyViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -49,7 +49,7 @@ final class BooksViewModel: AnyViewModel { private var newSet: DataSetType = .init() private var cancellables = Set() - init(screen: AnyBooksScreen!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { + init(screen: BooksScreen!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { self.searchText = .init(searchText) super.init(screen: screen) self.previousBook = previousBook From e94b6eb88d75e6ec5bde6201eb056f606b1aea06 Mon Sep 17 00:00:00 2001 From: RomanPodymov Date: Sun, 27 Apr 2025 13:14:38 +0200 Subject: [PATCH 05/14] Runnable --- Bookie/UI/BooksScreenSwiftUI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bookie/UI/BooksScreenSwiftUI.swift b/Bookie/UI/BooksScreenSwiftUI.swift index f30de25..988da2c 100644 --- a/Bookie/UI/BooksScreenSwiftUI.swift +++ b/Bookie/UI/BooksScreenSwiftUI.swift @@ -86,7 +86,7 @@ final class BooksScreenSwiftUI: UIHostingController, AnyBoo searchText: Self.searchTextBinding(viewModel: viewModel) ) ) - viewModel.screen = self + // viewModel.screen = self viewModel.ready() } From 4d39a9d25c70d7418e22d6aa011682701272bba4 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Sun, 11 May 2025 18:35:03 +0200 Subject: [PATCH 06/14] Using BasicViewModel --- Bookie/UI/BookScreen.swift | 2 +- Bookie/UI/BookScreenSwiftUI.swift | 2 +- Bookie/UI/BooksScreen.swift | 2 +- Bookie/UI/BooksScreenSwiftUI.swift | 2 +- Bookie/ViewModel/BookViewModel.swift | 8 ++++++-- Bookie/ViewModel/BooksViewModel.swift | 9 +++++++-- project.yml | 6 +++--- 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Bookie/UI/BookScreen.swift b/Bookie/UI/BookScreen.swift index 02d9f04..07f6b46 100644 --- a/Bookie/UI/BookScreen.swift +++ b/Bookie/UI/BookScreen.swift @@ -17,7 +17,7 @@ final class BookScreen: UIViewController { private unowned var bookImage: UIImageView! private unowned var metadataRootView: UIView! - private var viewModel: BookViewModel! + var viewModel: BookViewModel! init(_ data: Book?) { super.init(nibName: nil, bundle: nil) diff --git a/Bookie/UI/BookScreenSwiftUI.swift b/Bookie/UI/BookScreenSwiftUI.swift index f788dfd..116be18 100644 --- a/Bookie/UI/BookScreenSwiftUI.swift +++ b/Bookie/UI/BookScreenSwiftUI.swift @@ -56,7 +56,7 @@ struct BookScreenRootView: View { } final class BookScreenSwiftUI: UIHostingController, AnyBookScreen { - private var viewModel: BookViewModel! + var viewModel: BookViewModel! init(_ data: Book?) { viewModel = BookViewModel(screen: nil, data: data) diff --git a/Bookie/UI/BooksScreen.swift b/Bookie/UI/BooksScreen.swift index 1e9ebf3..3a42ec5 100644 --- a/Bookie/UI/BooksScreen.swift +++ b/Bookie/UI/BooksScreen.swift @@ -21,7 +21,7 @@ final class BooksScreen: UIViewController { private unowned var rootView: UICollectionView! private unowned var loadingView: LoadingView! - private var viewModel: BooksViewModel! + var viewModel: BooksViewModel! init(searchText: String, previousBook: Book?) { super.init(nibName: nil, bundle: nil) diff --git a/Bookie/UI/BooksScreenSwiftUI.swift b/Bookie/UI/BooksScreenSwiftUI.swift index 988da2c..c625fda 100644 --- a/Bookie/UI/BooksScreenSwiftUI.swift +++ b/Bookie/UI/BooksScreenSwiftUI.swift @@ -73,7 +73,7 @@ struct BooksScreenRootView: View { } final class BooksScreenSwiftUI: UIHostingController, AnyBooksScreen { - private var viewModel: BooksViewModel! + var viewModel: BooksViewModel! init(searchText: String, previousBook: Book?) { viewModel = .init(screen: nil, searchText: searchText, previousBook: previousBook) diff --git a/Bookie/ViewModel/BookViewModel.swift b/Bookie/ViewModel/BookViewModel.swift index 5e446b8..35079fb 100644 --- a/Bookie/ViewModel/BookViewModel.swift +++ b/Bookie/ViewModel/BookViewModel.swift @@ -9,12 +9,12 @@ import JobInterviewAssignmentKit import UIKit -protocol AnyBookScreen: AnyScreen { +protocol AnyBookScreen: Screen { @MainActor init(_ data: Book?) } -class BookViewModel: AnyViewModel { +class BookViewModel: BasicViewModel { var data: Book? init(screen: BookScreen!, data: Book? = nil) { @@ -22,6 +22,10 @@ class BookViewModel: AnyViewModel { self.data = data } + required init(screen: ScreenType) { + super.init(screen: screen) + } + @MainActor func openBook() async { await UIApplication.shared.open( diff --git a/Bookie/ViewModel/BooksViewModel.swift b/Bookie/ViewModel/BooksViewModel.swift index c311a37..9959984 100644 --- a/Bookie/ViewModel/BooksViewModel.swift +++ b/Bookie/ViewModel/BooksViewModel.swift @@ -14,7 +14,7 @@ import JobInterviewAssignmentKit import Moya import OrderedCollections -protocol AnyBooksScreen: AnyScreen, Sendable { +protocol AnyBooksScreen: Screen, Sendable { @MainActor init(searchText: String, previousBook: Book?) func onNewDataReceived(oldSet: DataSetType, newSet: DataSetType) async @@ -41,7 +41,7 @@ enum BooksViewModelError: Error { case requestError(Error) } -final class BooksViewModel: AnyViewModel { +final class BooksViewModel: BasicViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -58,6 +58,11 @@ final class BooksViewModel: AnyViewModel { self.data = data } + required init(screen: ScreenType) { + searchText = .init("") + super.init(screen: screen) + } + func reloadData() async { guard let source = dependenciesContainer.resolve(RemoteDataSource.self), let localSource = dependenciesContainer.resolve(LocalDataSource.self) diff --git a/project.yml b/project.yml index 7a8a442..defc76d 100644 --- a/project.yml +++ b/project.yml @@ -81,12 +81,12 @@ targets: NSAppTransportSecurity: NSAllowsArbitraryLoads: YES preBuildScripts: - - script: "mint run swiftgen" + - script: "/opt/homebrew/bin/mint run swiftgen" name: SwiftGen postCompileScripts: - - script: "mint run swiftformat . --swiftversion 5.5" + - script: "/opt/homebrew/bin/mint run swiftformat . --swiftversion 5.5" name: SwiftFormat - - script: "mint run swiftlint" + - script: "/opt/homebrew/bin/mint run swiftlint" name: SwiftLint BookieAppTests: settings: From e4043fa8136dfee14c475035127fbe53c0864c32 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 15:35:00 +0200 Subject: [PATCH 07/14] Fixing errors --- Bookie/ViewModel/BookViewModel.swift | 7 ++----- Bookie/ViewModel/BooksViewModel.swift | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Bookie/ViewModel/BookViewModel.swift b/Bookie/ViewModel/BookViewModel.swift index 35079fb..9f28b94 100644 --- a/Bookie/ViewModel/BookViewModel.swift +++ b/Bookie/ViewModel/BookViewModel.swift @@ -18,12 +18,9 @@ class BookViewModel: BasicViewModel { var data: Book? init(screen: BookScreen!, data: Book? = nil) { - super.init(screen: screen) self.data = data - } - - required init(screen: ScreenType) { - super.init(screen: screen) + super.init() + self.screen = screen } @MainActor diff --git a/Bookie/ViewModel/BooksViewModel.swift b/Bookie/ViewModel/BooksViewModel.swift index 9959984..61ea0d0 100644 --- a/Bookie/ViewModel/BooksViewModel.swift +++ b/Bookie/ViewModel/BooksViewModel.swift @@ -41,6 +41,12 @@ enum BooksViewModelError: Error { case requestError(Error) } +struct SetupParams { + let searchText: String + let previousBook: Book? + let data: BookResponse? +} + final class BooksViewModel: BasicViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -53,14 +59,10 @@ final class BooksViewModel: BasicViewModel { init(screen: BooksScreen!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { self.searchText = .init(searchText) - super.init(screen: screen) self.previousBook = previousBook self.data = data - } - - required init(screen: ScreenType) { - searchText = .init("") - super.init(screen: screen) + super.init() + self.screen = screen } func reloadData() async { @@ -81,9 +83,9 @@ final class BooksViewModel: BasicViewModel { data = books oldSet = newSet - await (screen as? AnyBooksScreen)?.onNewDataReceived(oldSet: oldSet, newSet: createSet(from: books)) + await screen.onNewDataReceived(oldSet: oldSet, newSet: createSet(from: books)) } catch { - await (screen as? AnyBooksScreen)?.onNewDataError(error) + await screen.onNewDataError(error) } } From 879d4d047739c0a7385773f06237cd13e0ebd0e8 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 18:24:11 +0200 Subject: [PATCH 08/14] Uncommenting --- Bookie/DI/CoordinatorSwiftUI.swift | 4 ++-- Bookie/UI/BooksScreen.swift | 2 +- Bookie/UI/BooksScreenSwiftUI.swift | 8 ++++---- Bookie/ViewModel/BooksViewModel.swift | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Bookie/DI/CoordinatorSwiftUI.swift b/Bookie/DI/CoordinatorSwiftUI.swift index 3096a41..f690cfe 100644 --- a/Bookie/DI/CoordinatorSwiftUI.swift +++ b/Bookie/DI/CoordinatorSwiftUI.swift @@ -13,14 +13,14 @@ class CoordinatorSwiftUI: Coordinator { override class func createRootScreen( searchText: String, previousBook: Book? - ) -> (AnyBooksScreen & UIViewController) { + ) -> (any AnyBooksScreen & UIViewController) { BooksScreenSwiftUI(searchText: searchText, previousBook: previousBook) } @MainActor override class func createDetailScreen( _ data: Book - ) -> (AnyBookScreen & UIViewController) { + ) -> (any AnyBookScreen & UIViewController) { BookScreenSwiftUI(data) } } diff --git a/Bookie/UI/BooksScreen.swift b/Bookie/UI/BooksScreen.swift index 3a42ec5..c1cace3 100644 --- a/Bookie/UI/BooksScreen.swift +++ b/Bookie/UI/BooksScreen.swift @@ -21,7 +21,7 @@ final class BooksScreen: UIViewController { private unowned var rootView: UICollectionView! private unowned var loadingView: LoadingView! - var viewModel: BooksViewModel! + var viewModel: BooksViewModel! init(searchText: String, previousBook: Book?) { super.init(nibName: nil, bundle: nil) diff --git a/Bookie/UI/BooksScreenSwiftUI.swift b/Bookie/UI/BooksScreenSwiftUI.swift index c625fda..73a70b1 100644 --- a/Bookie/UI/BooksScreenSwiftUI.swift +++ b/Bookie/UI/BooksScreenSwiftUI.swift @@ -73,7 +73,7 @@ struct BooksScreenRootView: View { } final class BooksScreenSwiftUI: UIHostingController, AnyBooksScreen { - var viewModel: BooksViewModel! + var viewModel: BooksViewModel! init(searchText: String, previousBook: Book?) { viewModel = .init(screen: nil, searchText: searchText, previousBook: previousBook) @@ -86,7 +86,7 @@ final class BooksScreenSwiftUI: UIHostingController, AnyBoo searchText: Self.searchTextBinding(viewModel: viewModel) ) ) - // viewModel.screen = self + viewModel.screen = self viewModel.ready() } @@ -96,7 +96,7 @@ final class BooksScreenSwiftUI: UIHostingController, AnyBoo private static func selectedBook( previousBook: Book?, - viewModel: BooksViewModel + viewModel: BooksViewModel ) -> Binding { .init(get: { previousBook @@ -112,7 +112,7 @@ final class BooksScreenSwiftUI: UIHostingController, AnyBoo }) } - private static func searchTextBinding(viewModel: BooksViewModel) -> Binding { + private static func searchTextBinding(viewModel: BooksViewModel) -> Binding { .init(get: { [weak viewModel] in viewModel?.searchText.value ?? "" }, set: { [weak viewModel] in diff --git a/Bookie/ViewModel/BooksViewModel.swift b/Bookie/ViewModel/BooksViewModel.swift index 61ea0d0..f8341b7 100644 --- a/Bookie/ViewModel/BooksViewModel.swift +++ b/Bookie/ViewModel/BooksViewModel.swift @@ -47,7 +47,7 @@ struct SetupParams { let data: BookResponse? } -final class BooksViewModel: BasicViewModel { +final class BooksViewModel: BasicViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -62,7 +62,7 @@ final class BooksViewModel: BasicViewModel { self.previousBook = previousBook self.data = data super.init() - self.screen = screen + self.screen = screen as? BooksScreenType } func reloadData() async { From f42b36b88e87229fbbb6a4cf605d629c5f3fd924 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 18:39:15 +0200 Subject: [PATCH 09/14] All uncommented --- Bookie/DI/DI.swift | 2 +- Bookie/UI/BookScreen.swift | 2 +- Bookie/UI/BookScreenSwiftUI.swift | 6 +++--- Bookie/ViewModel/BookViewModel.swift | 4 ++-- Bookie/ViewModel/BooksViewModel.swift | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Bookie/DI/DI.swift b/Bookie/DI/DI.swift index ccb5cf7..6831db2 100644 --- a/Bookie/DI/DI.swift +++ b/Bookie/DI/DI.swift @@ -31,7 +31,7 @@ extension Container: @retroactive Then {} let dependenciesContainer = Container().then { result in let objectScope: ObjectScope = .container result.register(AnyCoordinator.self) { _ in - CoordinatorSwiftUI() + Coordinator() }.inObjectScope(objectScope) result.register(Stylesheet.self) { _ in MainStylesheet() diff --git a/Bookie/UI/BookScreen.swift b/Bookie/UI/BookScreen.swift index 07f6b46..3e64836 100644 --- a/Bookie/UI/BookScreen.swift +++ b/Bookie/UI/BookScreen.swift @@ -17,7 +17,7 @@ final class BookScreen: UIViewController { private unowned var bookImage: UIImageView! private unowned var metadataRootView: UIView! - var viewModel: BookViewModel! + var viewModel: BookViewModel! init(_ data: Book?) { super.init(nibName: nil, bundle: nil) diff --git a/Bookie/UI/BookScreenSwiftUI.swift b/Bookie/UI/BookScreenSwiftUI.swift index 116be18..54130d4 100644 --- a/Bookie/UI/BookScreenSwiftUI.swift +++ b/Bookie/UI/BookScreenSwiftUI.swift @@ -56,7 +56,7 @@ struct BookScreenRootView: View { } final class BookScreenSwiftUI: UIHostingController, AnyBookScreen { - var viewModel: BookViewModel! + var viewModel: BookViewModel! init(_ data: Book?) { viewModel = BookViewModel(screen: nil, data: data) @@ -66,14 +66,14 @@ final class BookScreenSwiftUI: UIHostingController, AnyBookS data: data ) ) - // viewModel.screen = self + viewModel.screen = self } @MainActor @preconcurrency dynamic required init?(coder _: NSCoder) { nil } - private static func backPressedBinding(viewModel: BookViewModel) -> Binding { + private static func backPressedBinding(viewModel: BookViewModel) -> Binding { .init(get: { false }, set: { _ in diff --git a/Bookie/ViewModel/BookViewModel.swift b/Bookie/ViewModel/BookViewModel.swift index 9f28b94..304434b 100644 --- a/Bookie/ViewModel/BookViewModel.swift +++ b/Bookie/ViewModel/BookViewModel.swift @@ -14,10 +14,10 @@ protocol AnyBookScreen: Screen { init(_ data: Book?) } -class BookViewModel: BasicViewModel { +class BookViewModel: BasicViewModel { var data: Book? - init(screen: BookScreen!, data: Book? = nil) { + init(screen: BookScreenType!, data: Book? = nil) { self.data = data super.init() self.screen = screen diff --git a/Bookie/ViewModel/BooksViewModel.swift b/Bookie/ViewModel/BooksViewModel.swift index f8341b7..956c8d1 100644 --- a/Bookie/ViewModel/BooksViewModel.swift +++ b/Bookie/ViewModel/BooksViewModel.swift @@ -57,12 +57,12 @@ final class BooksViewModel: BasicVi private var newSet: DataSetType = .init() private var cancellables = Set() - init(screen: BooksScreen!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { + init(screen: BooksScreenType!, searchText: String, previousBook: Book?, data: BookResponse? = nil) { self.searchText = .init(searchText) self.previousBook = previousBook self.data = data super.init() - self.screen = screen as? BooksScreenType + self.screen = screen } func reloadData() async { From cd196efb913e13eadf744b8a4504dd6b6b5174f8 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 18:43:20 +0200 Subject: [PATCH 10/14] Using remote version --- project.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/project.yml b/project.yml index defc76d..4698d3d 100644 --- a/project.yml +++ b/project.yml @@ -45,7 +45,8 @@ packages: url: https://github.com/apple/swift-collections version: 1.1.4 JobInterviewAssignmentKit: - path: ../JobInterviewAssignmentKit + url: https://github.com/RomanPodymov/JobInterviewAssignmentKit + version: 0.0.1 RealmSwift: url: https://github.com/realm/realm-swift.git version: 20.0.2 From b10c0830ed846a2c9be0d0748e15a834996b7774 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 18:46:12 +0200 Subject: [PATCH 11/14] Remove unused code --- Bookie/ViewModel/BooksViewModel.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Bookie/ViewModel/BooksViewModel.swift b/Bookie/ViewModel/BooksViewModel.swift index 956c8d1..98eb642 100644 --- a/Bookie/ViewModel/BooksViewModel.swift +++ b/Bookie/ViewModel/BooksViewModel.swift @@ -41,12 +41,6 @@ enum BooksViewModelError: Error { case requestError(Error) } -struct SetupParams { - let searchText: String - let previousBook: Book? - let data: BookResponse? -} - final class BooksViewModel: BasicViewModel { let searchText: CurrentValueSubject var previousBook: Book? @@ -83,9 +77,9 @@ final class BooksViewModel: BasicVi data = books oldSet = newSet - await screen.onNewDataReceived(oldSet: oldSet, newSet: createSet(from: books)) + await screen?.onNewDataReceived(oldSet: oldSet, newSet: createSet(from: books)) } catch { - await screen.onNewDataError(error) + await screen?.onNewDataError(error) } } From 4c2973b13d6b95e82978dfebb31f8f4ee75cad9b Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 19:55:19 +0200 Subject: [PATCH 12/14] Fix tests --- BookieTests/BookieTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BookieTests/BookieTests.swift b/BookieTests/BookieTests.swift index 0688340..3c1b86b 100644 --- a/BookieTests/BookieTests.swift +++ b/BookieTests/BookieTests.swift @@ -17,6 +17,8 @@ extension Book: @retroactive Equatable { } private final class TestScreen: AnyBooksScreen { + var viewModel: BooksViewModel! + @MainActor var testCheck: (@Sendable (DataSetType) -> Void)! From 392ad4ad57ffabb527e691cfdd4e9857fc0002a9 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 21:06:08 +0200 Subject: [PATCH 13/14] Init viewModel --- BookieTests/BookieTests.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/BookieTests/BookieTests.swift b/BookieTests/BookieTests.swift index 3c1b86b..2840022 100644 --- a/BookieTests/BookieTests.swift +++ b/BookieTests/BookieTests.swift @@ -22,7 +22,9 @@ private final class TestScreen: AnyBooksScreen { @MainActor var testCheck: (@Sendable (DataSetType) -> Void)! - required init(searchText _: String, previousBook _: Book?) {} + required init(searchText: String, previousBook: Book?) { + viewModel = BooksViewModel(screen: self, searchText: searchText, previousBook: previousBook) + } func onNewDataReceived(oldSet _: DataSetType, newSet: DataSetType) async { await testCheck(newSet) @@ -93,8 +95,7 @@ class BookieTests: XCTestCase { } // When - let viewModel = BooksViewModel(screen: screen, searchText: "", previousBook: nil) - await viewModel.reloadData() + await screen.viewModel.reloadData() } } From d15477f5f9eaf33fb3085b2354e2e697e4b9ac54 Mon Sep 17 00:00:00 2001 From: Roman Podymov Date: Wed, 14 May 2025 22:22:19 +0200 Subject: [PATCH 14/14] any --- Bookie/DI/Coordinator.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bookie/DI/Coordinator.swift b/Bookie/DI/Coordinator.swift index 52ef7aa..25c3393 100644 --- a/Bookie/DI/Coordinator.swift +++ b/Bookie/DI/Coordinator.swift @@ -35,14 +35,14 @@ class Coordinator: AnyCoordinator { class func createRootScreen( searchText: String, previousBook: Book? - ) -> (AnyBooksScreen & UIViewController) { + ) -> (any AnyBooksScreen & UIViewController) { BooksScreen(searchText: searchText, previousBook: previousBook) } @MainActor class func createDetailScreen( _ data: Book - ) -> (AnyBookScreen & UIViewController) { + ) -> (any AnyBookScreen & UIViewController) { BookScreen(data) }