Skip to content

Commit 976e55f

Browse files
authored
Initial commit
1 parent 56d1e99 commit 976e55f

File tree

80 files changed

+5270
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+5270
-1
lines changed

ExampleMVVM.xcodeproj/project.pbxproj

+1,209
Large diffs are not rendered by default.

ExampleMVVM.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<array/>
5+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1010"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "1FA53388201E1FDE00747E55"
18+
BuildableName = "ExampleMVVM.app"
19+
BlueprintName = "ExampleMVVM"
20+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
<TestableReference
32+
skipped = "NO">
33+
<BuildableReference
34+
BuildableIdentifier = "primary"
35+
BlueprintIdentifier = "1FA5339C201E1FDE00747E55"
36+
BuildableName = "ExampleMVVMTests.xctest"
37+
BlueprintName = "ExampleMVVMTests"
38+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
39+
</BuildableReference>
40+
</TestableReference>
41+
<TestableReference
42+
skipped = "NO">
43+
<BuildableReference
44+
BuildableIdentifier = "primary"
45+
BlueprintIdentifier = "1F02DE3122F8507500E40C3A"
46+
BuildableName = "ExampleMVVMUITests.xctest"
47+
BlueprintName = "ExampleMVVMUITests"
48+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
49+
</BuildableReference>
50+
</TestableReference>
51+
</Testables>
52+
<MacroExpansion>
53+
<BuildableReference
54+
BuildableIdentifier = "primary"
55+
BlueprintIdentifier = "1FA53388201E1FDE00747E55"
56+
BuildableName = "ExampleMVVM.app"
57+
BlueprintName = "ExampleMVVM"
58+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
59+
</BuildableReference>
60+
</MacroExpansion>
61+
<AdditionalOptions>
62+
</AdditionalOptions>
63+
</TestAction>
64+
<LaunchAction
65+
buildConfiguration = "Debug"
66+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
67+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
68+
launchStyle = "0"
69+
useCustomWorkingDirectory = "NO"
70+
ignoresPersistentStateOnLaunch = "NO"
71+
debugDocumentVersioning = "YES"
72+
debugServiceExtension = "internal"
73+
allowLocationSimulation = "YES">
74+
<BuildableProductRunnable
75+
runnableDebuggingMode = "0">
76+
<BuildableReference
77+
BuildableIdentifier = "primary"
78+
BlueprintIdentifier = "1FA53388201E1FDE00747E55"
79+
BuildableName = "ExampleMVVM.app"
80+
BlueprintName = "ExampleMVVM"
81+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
82+
</BuildableReference>
83+
</BuildableProductRunnable>
84+
<AdditionalOptions>
85+
</AdditionalOptions>
86+
</LaunchAction>
87+
<ProfileAction
88+
buildConfiguration = "Release"
89+
shouldUseLaunchSchemeArgsEnv = "YES"
90+
savedToolIdentifier = ""
91+
useCustomWorkingDirectory = "NO"
92+
debugDocumentVersioning = "YES">
93+
<BuildableProductRunnable
94+
runnableDebuggingMode = "0">
95+
<BuildableReference
96+
BuildableIdentifier = "primary"
97+
BlueprintIdentifier = "1FA53388201E1FDE00747E55"
98+
BuildableName = "ExampleMVVM.app"
99+
BlueprintName = "ExampleMVVM"
100+
ReferencedContainer = "container:ExampleMVVM.xcodeproj">
101+
</BuildableReference>
102+
</BuildableProductRunnable>
103+
</ProfileAction>
104+
<AnalyzeAction
105+
buildConfiguration = "Debug">
106+
</AnalyzeAction>
107+
<ArchiveAction
108+
buildConfiguration = "Release"
109+
revealArchiveInOrganizer = "YES">
110+
</ArchiveAction>
111+
</Scheme>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Bucket
3+
uuid = "1C920B8E-6619-40F3-B1DB-15CE3E81F142"
4+
type = "1"
5+
version = "2.0">
6+
</Bucket>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>SchemeUserState</key>
6+
<dict>
7+
<key>ExampleMVVM.xcscheme_^#shared#^_</key>
8+
<dict>
9+
<key>orderHint</key>
10+
<integer>0</integer>
11+
</dict>
12+
</dict>
13+
<key>SuppressBuildableAutocreation</key>
14+
<dict>
15+
<key>1FA53388201E1FDE00747E55</key>
16+
<dict>
17+
<key>primary</key>
18+
<true/>
19+
</dict>
20+
<key>1FA5339C201E1FDE00747E55</key>
21+
<dict>
22+
<key>primary</key>
23+
<true/>
24+
</dict>
25+
</dict>
26+
</dict>
27+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// AppAppearance.swift
3+
// ExampleMVVM
4+
//
5+
// Created by Oleh on 23.09.18.
6+
//
7+
8+
import Foundation
9+
import UIKit
10+
11+
final class AppAppearance {
12+
13+
static func setupAppearance() {
14+
UINavigationBar.appearance().barTintColor = .black
15+
UINavigationBar.appearance().tintColor = .white
16+
UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
17+
}
18+
}
19+
20+
extension UINavigationController {
21+
@objc override open var preferredStatusBarStyle: UIStatusBarStyle {
22+
return .lightContent
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// AppConfigurations.swift
3+
// ExampleMVVM
4+
//
5+
// Created by Oleh Kudinov on 25.02.19.
6+
//
7+
8+
import Foundation
9+
10+
final class AppConfigurations {
11+
lazy var apiKey: String = {
12+
guard let apiKey = Bundle.main.object(forInfoDictionaryKey: "ApiKey") as? String else {
13+
fatalError("ApiKey must not be empty in plist")
14+
}
15+
return apiKey
16+
}()
17+
lazy var apiBaseURL: String = {
18+
guard let apiBaseURL = Bundle.main.object(forInfoDictionaryKey: "ApiBaseURL") as? String else {
19+
fatalError("ApiBaseURL must not be empty in plist")
20+
}
21+
return apiBaseURL
22+
}()
23+
lazy var imagesBaseURL: String = {
24+
guard let imageBaseURL = Bundle.main.object(forInfoDictionaryKey: "ImageBaseURL") as? String else {
25+
fatalError("ApiBaseURL must not be empty in plist")
26+
}
27+
return imageBaseURL
28+
}()
29+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// AppDelegate.swift
3+
// ExampleMVVM
4+
//
5+
// Created by Oleh Kudinov on 01.10.18.
6+
//
7+
8+
import UIKit
9+
10+
@UIApplicationMain
11+
class AppDelegate: UIResponder, UIApplicationDelegate {
12+
13+
let appDIContainer = AppDIContainer()
14+
var window: UIWindow?
15+
16+
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
17+
18+
AppAppearance.setupAppearance()
19+
20+
window = UIWindow(frame: UIScreen.main.bounds)
21+
let moviesListViewController = appDIContainer.makeMoviesSceneDIContainer().makeMoviesListViewController()
22+
window?.rootViewController = UINavigationController(rootViewController: moviesListViewController)
23+
window?.makeKeyAndVisible()
24+
25+
return true
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// DIContainer.swift
3+
// ExampleMVVM
4+
//
5+
// Created by Oleh Kudinov on 01.10.18.
6+
//
7+
8+
import Foundation
9+
import UIKit
10+
11+
final class AppDIContainer {
12+
13+
lazy var appConfigurations = AppConfigurations()
14+
15+
// MARK: - Network
16+
lazy var apiDataTransferService: DataTransfer = {
17+
let config = ApiDataNetworkConfig(baseURL: URL(string: appConfigurations.apiBaseURL)!,
18+
queryParameters: ["api_key": appConfigurations.apiKey])
19+
20+
let apiDataNetwork = DefaultNetworkService(session: URLSession.shared,
21+
config: config)
22+
return DefaultDataTransferService(with: apiDataNetwork)
23+
}()
24+
lazy var imageDataTransferService: DataTransfer = {
25+
let config = ApiDataNetworkConfig(baseURL: URL(string: appConfigurations.imagesBaseURL)!)
26+
let carrierLogosDataNetwork = DefaultNetworkService(session: URLSession.shared,
27+
config: config)
28+
return DefaultDataTransferService(with: carrierLogosDataNetwork)
29+
}()
30+
31+
// DIContainers of scenes
32+
func makeMoviesSceneDIContainer() -> MoviesSceneDIContainer {
33+
let dependencies = MoviesSceneDIContainer.Dependencies(apiDataTransferService: apiDataTransferService,
34+
imageDataTransferService: imageDataTransferService)
35+
return MoviesSceneDIContainer(dependencies: dependencies)
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//
2+
// MoviesSceneDIContainer.swift
3+
// ExampleMVVM
4+
//
5+
// Created by Oleh Kudinov on 03.03.19.
6+
//
7+
8+
import Foundation
9+
import UIKit
10+
// SwiftUI
11+
//import SwiftUI
12+
13+
final class MoviesSceneDIContainer {
14+
15+
struct Dependencies {
16+
let apiDataTransferService: DataTransfer
17+
let imageDataTransferService: DataTransfer
18+
}
19+
20+
private let dependencies: Dependencies
21+
22+
// MARK: - Persistent Storage
23+
lazy var moviesQueriesStorage: MoviesQueriesStorage = CoreDataStorage(maxStorageLimit: 10)
24+
25+
init(dependencies: Dependencies) {
26+
self.dependencies = dependencies
27+
}
28+
29+
// MARK: - Use Cases
30+
func makeSearchMoviesUseCase() -> SearchMoviesUseCase {
31+
return DefaultSearchMoviesUseCase(moviesRepository: makeMoviesRepository(),
32+
moviesQueriesRepository: makeMoviesQueriesRepository())
33+
}
34+
35+
func makeFetchMoviesRecentQueriesUseCase() -> FetchMoviesRecentQueriesUseCase {
36+
return DefaultFetchMoviesRecentQueriesUseCase(moviesQueriesRepository: makeMoviesQueriesRepository())
37+
}
38+
39+
// MARK: - Data Sources
40+
func makeMoviesRepository() -> MoviesRepository {
41+
return DefaultMoviesRepository(dataTransferService: dependencies.apiDataTransferService)
42+
}
43+
func makeMoviesQueriesRepository() -> MoviesQueriesRepository {
44+
return DefaultMoviesQueriesRepository(dataTransferService: dependencies.apiDataTransferService,
45+
moviesQueriesPersistentStorage: moviesQueriesStorage)
46+
}
47+
func makePosterImagesRepository() -> PosterImagesRepository {
48+
return DefaultPosterImagesRepository(dataTransferService: dependencies.imageDataTransferService,
49+
imageNotFoundData: UIImage(named: "image_not_found")?.pngData())
50+
}
51+
52+
// MARK: - Movies List
53+
func makeMoviesListViewController() -> UIViewController {
54+
return MoviesListViewController.create(with: makeMoviesListViewModel(), moviesListViewControllersFactory: self)
55+
}
56+
57+
func makeMoviesListViewModel() -> MoviesListViewModel {
58+
return MoviesListViewModel(searchMoviesUseCase: makeSearchMoviesUseCase(),
59+
posterImagesRepository: makePosterImagesRepository())
60+
}
61+
62+
// MARK: - Movie Details
63+
func makeMoviesDetailsViewController(title: String,
64+
overview: String,
65+
posterPlaceholderImage: Data?,
66+
posterPath: String?) -> UIViewController {
67+
return MovieDetailsViewController.create(with: makeMoviesDetailsViewModel(title: title,
68+
overview: overview,
69+
posterPlaceholderImage: posterPlaceholderImage,
70+
posterPath: posterPath))
71+
}
72+
73+
func makeMoviesDetailsViewModel(title: String,
74+
overview: String,
75+
posterPlaceholderImage: Data?,
76+
posterPath: String?) -> MovieDetailsViewModel {
77+
return MovieDetailsViewModel(title: title,
78+
overview: overview,
79+
posterPlaceholderImage: posterPlaceholderImage,
80+
posterPath: posterPath,
81+
posterImagesRepository: makePosterImagesRepository())
82+
}
83+
84+
// MARK: - Movies Queries Suggestions List
85+
func makeMoviesQueriesSuggestionsListViewController(delegate: MoviesQueryListViewModelDelegate) -> UIViewController {
86+
// if #available(iOS 13.0, *) { // SwiftUI
87+
// return UIHostingController(rootView: MoviesQueryListView(viewModel: makeMoviesQueryListViewModelWrapper(delegate: delegate)))
88+
// } else { // UIKit
89+
return MoviesQueriesTableViewController.create(with: makeMoviesQueryListViewModel(delegate: delegate))
90+
// }
91+
}
92+
93+
func makeMoviesQueryListViewModel(delegate: MoviesQueryListViewModelDelegate) -> MoviesQueryListViewModel {
94+
return MoviesQueryListViewModel(numberOfQueriesToShow: 10,
95+
fetchMoviesRecentQueriesUseCase: makeFetchMoviesRecentQueriesUseCase(),
96+
delegate: delegate)
97+
}
98+
// SwiftUI
99+
// @available(iOS 13.0, *)
100+
// func makeMoviesQueryListViewModelWrapper(delegate: MoviesQueryListViewModelDelegate) -> MoviesQueryListViewModelWrapper {
101+
// return MoviesQueryListViewModelWrapper(numberOfQueriesToShow: 10,
102+
// fetchMoviesRecentQueriesUseCase: makeFetchMoviesRecentQueriesUseCase(),
103+
// delegate: delegate)
104+
// }
105+
}
106+
107+
extension MoviesSceneDIContainer: MoviesListViewControllersFactory {}

0 commit comments

Comments
 (0)