├── MVVM with RxSwift
├── Assets
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ └── MVVM_with_RxSwift.xcdatamodeld
│ │ ├── .xccurrentversion
│ │ └── MVVM_with_RxSwift.xcdatamodel
│ │ └── contents
├── Module
│ ├── UseCase
│ │ ├── UsersUseCaseProtocol.swift
│ │ └── UsersUseCase.swift
│ ├── Model
│ │ ├── UsersSectionModel.swift
│ │ └── UsersModel.swift
│ ├── ViewModel
│ │ └── UsersViewModel.swift
│ └── ViewController
│ │ └── UsersViewController.swift
├── States
│ └── States.swift
├── Extentions
│ ├── Alerts+Ext.swift
│ └── LoadingIndicator+Ext.swift
├── Info.plist
├── Storyboard
│ └── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
└── AppDelegate
│ ├── SceneDelegate.swift
│ └── AppDelegate.swift
├── MVVM with RxSwift.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── alifayed.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
├── MVVM with RxSwiftTests
├── UsersModuleTests
│ ├── Stubs and Mocks
│ │ ├── JSONMocking.swift
│ │ └── UsersUseCaseMock.swift
│ ├── UsersViewModelTests.swift
│ └── UsersUseCaseTests.swift
└── StubRequests.swift
├── Podfile
├── MVVM with RxSwiftUITests
├── MVVM_with_RxSwiftUITestsLaunchTests.swift
└── MVVM_with_RxSwiftUITests.swift
└── README.md
/MVVM with RxSwift/Assets/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/MVVM with RxSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Assets/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/UseCase/UsersUseCaseProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersUseCaseProtocol.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 | import Combine
10 |
11 | protocol UsersUseCaseProtocol {
12 | func fetchUsers() -> AnyPublisher<[Users], Error>?
13 | }
14 |
--------------------------------------------------------------------------------
/MVVM with RxSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Assets/MVVM_with_RxSwift.xcdatamodeld/.xccurrentversion:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | _XCCurrentVersionName
6 | MVVM_with_RxSwift.xcdatamodel
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/States/States.swift:
--------------------------------------------------------------------------------
1 | //
2 | // States.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 | import RxCocoa
10 | import RxSwift
11 |
12 | class States {
13 | var loadingState = BehaviorRelay(value: false)
14 | var errorState = BehaviorRelay<(Bool, String)>(value: (false, ""))
15 | }
16 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftTests/UsersModuleTests/Stubs and Mocks/JSONMocking.swift:
--------------------------------------------------------------------------------
1 | //
2 | // fakeJSON.swift
3 | // MVVM with RxSwiftTests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 |
10 | class JSONMocking {
11 | static let shared = JSONMocking()
12 | private init() {}
13 | let fakeJSON: [String: Any] = [
14 | "login" : "mojombo"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Assets/MVVM_with_RxSwift.xcdatamodeld/MVVM_with_RxSwift.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/Model/UsersSectionModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersSectionModel.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import RxDataSources
9 |
10 | struct UsersSectionModel {
11 | var header: String
12 | var items: [Users]
13 | }
14 | extension UsersSectionModel: SectionModelType {
15 | init(original: UsersSectionModel, items: [Users]) {
16 | self = original
17 | self.items = items
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MVVM with RxSwift.xcodeproj/xcuserdata/alifayed.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | MVVM with RxSwift.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 10
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftTests/UsersModuleTests/Stubs and Mocks/UsersUseCaseMock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersUseCaseMock.swift
3 | // MVVM with RxSwiftTests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 | import Combine
10 | @testable import MVVM_with_RxSwift
11 | class UsersUseCaseMock: UsersUseCaseProtocol {
12 | var fetchUsersComplete = false
13 | func fetchUsers() -> AnyPublisher<[Users], Error>? {
14 | fetchUsersComplete = true
15 | return nil
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/Model/UsersModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersModel.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 |
10 | struct Users {
11 | let userName: String?
12 |
13 | enum PostCodingKeys: String, CodingKey {
14 | case userName = "login"
15 | }
16 | }
17 | //MARK: - Decodable init
18 | extension Users: Decodable {
19 | init(from decoder: Decoder) throws {
20 | let container = try decoder.container(keyedBy: PostCodingKeys.self)
21 | userName = try container.decode(String.self, forKey: .userName)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | target 'MVVM with RxSwift' do
5 | # Comment the next line if you don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for MVVM with RxSwift
9 | pod 'RxSwift', '6.2.0'
10 | pod 'RxCocoa', '6.2.0'
11 | pod 'RxDataSources', '~> 5.0'
12 | pod 'MBProgressHUD', '~> 1.2.0'
13 | pod 'OHHTTPStubs/Swift'
14 |
15 | target 'MVVM with RxSwiftTests' do
16 | inherit! :search_paths
17 | # Pods for testing
18 | end
19 |
20 | target 'MVVM with RxSwiftUITests' do
21 | # Pods for testing
22 | end
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Extentions/Alerts+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Alerts+Ext.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import UIKit
9 |
10 | extension UIViewController {
11 | typealias ActionCompletion = ((UIAlertAction) -> Void)?
12 | func alertWithOneAction(title: String, msg: String, btnTitle: String, completion: ActionCompletion = nil) {
13 | let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
14 | let action = UIAlertAction(title: btnTitle, style: .default, handler: completion)
15 | alert.addAction(action)
16 | self.present(alert, animated: true)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftTests/StubRequests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StubRequests.swift
3 | // MVVM with RxSwiftTests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import OHHTTPStubs
9 |
10 | class StubRequests {
11 | static let shared = StubRequests()
12 | private init() {}
13 | func stubJSONrespone (jsonObject: [[String: Any]], header: [String: String]?, statusCode: Int32, absoluteStringWord: String) {
14 | stub(condition: { (urlRequest) -> Bool in
15 | return urlRequest.url?.absoluteString.contains(absoluteStringWord) ?? false
16 | }) { (_) -> HTTPStubsResponse in
17 | return HTTPStubsResponse(jsonObject: jsonObject, statusCode: statusCode, headers: header)
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Extentions/LoadingIndicator+Ext.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoadingIndicator+Ext.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import UIKit
9 | import MBProgressHUD
10 |
11 | extension UIViewController {
12 | func showIndicator(withTitle title: String, and Description:String) {
13 | let Indicator = MBProgressHUD.showAdded(to: self.view, animated: true)
14 | Indicator.label.text = title
15 | Indicator.isUserInteractionEnabled = false
16 | Indicator.detailsLabel.text = Description
17 | Indicator.show(animated: true)
18 | self.view.isUserInteractionEnabled = false
19 | }
20 | func hideIndicator() {
21 | MBProgressHUD.hide(for: self.view, animated: true)
22 | self.view.isUserInteractionEnabled = true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftTests/UsersModuleTests/UsersViewModelTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersViewModelTests.swift
3 | // MVVM with RxSwiftTests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import XCTest
9 | @testable import MVVM_with_RxSwift
10 | class UsersViewModelTests: XCTestCase {
11 | var sut: UsersViewModel!
12 | var usersUseCaseMock = UsersUseCaseMock()
13 | override func setUp() {
14 | sut = UsersViewModel(useCase: usersUseCaseMock)
15 | super.setUp()
16 | }
17 | override func tearDown() {
18 | sut = nil
19 | super.tearDown()
20 | }
21 | func testRequstData() throws {
22 | // when
23 | sut.fetchUsers()
24 | // then
25 | XCTAssertTrue(usersUseCaseMock.fetchUsersComplete, "Users fetch request called successfully")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftUITests/MVVM_with_RxSwiftUITestsLaunchTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MVVM_with_RxSwiftUITestsLaunchTests.swift
3 | // MVVM with RxSwiftUITests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import XCTest
9 |
10 | class MVVM_with_RxSwiftUITestsLaunchTests: XCTestCase {
11 |
12 | override class var runsForEachTargetApplicationUIConfiguration: Bool {
13 | true
14 | }
15 |
16 | override func setUpWithError() throws {
17 | continueAfterFailure = false
18 | }
19 |
20 | func testLaunch() throws {
21 | let app = XCUIApplication()
22 | app.launch()
23 |
24 | // Insert steps here to perform after app launch but before taking a screenshot,
25 | // such as logging into a test account or navigating somewhere in the app
26 |
27 | let attachment = XCTAttachment(screenshot: app.screenshot())
28 | attachment.name = "Launch Screen"
29 | attachment.lifetime = .keepAlways
30 | add(attachment)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/UseCase/UsersUseCase.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersUseCase.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 | import Combine
10 |
11 | class UsersUseCase: UsersUseCaseProtocol {
12 | static let shared = UsersUseCase()
13 | private init () {}
14 | func fetchUsers() -> AnyPublisher<[Users], Error>? {
15 | let url = URL(string: "https://api.github.com/users")
16 | return URLSession.shared.dataTaskPublisher(for: url!)
17 | .map({$0.data})
18 | .decode(type: [Users].self, decoder: JSONDecoder())
19 | .mapError({ error in
20 | switch error {
21 | case is Swift.DecodingError:
22 | return error
23 | default:
24 | return error
25 | }
26 | })
27 | .subscribe(on: DispatchQueue.global())
28 | .receive(on: DispatchQueue.main)
29 | .eraseToAnyPublisher()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftTests/UsersModuleTests/UsersUseCaseTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersUseCaseTests.swift
3 | // MVVM with RxSwiftTests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import XCTest
9 | import Combine
10 | @testable import MVVM_with_RxSwift
11 |
12 | class UsersUseCaseTests: XCTestCase {
13 | // sut = system under test
14 | var sut: UsersUseCase!
15 | let stubRequest = StubRequests.shared
16 | let jsonMock = JSONMocking.shared
17 | var observer: AnyCancellable?
18 | override func setUp() {
19 | super.setUp()
20 | sut = UsersUseCase.shared
21 | }
22 | override func tearDown() {
23 | sut = nil
24 | super.tearDown()
25 | }
26 | func testFetchNewsList() {
27 | let exception = self.expectation(description: "Fetch Users Failed")
28 | var expectedResults: [Users] = []
29 | stubRequest.stubJSONrespone(jsonObject: [jsonMock.fakeJSON], header: nil, statusCode: 200, absoluteStringWord: "/users")
30 | observer = sut.fetchUsers()?
31 | .sink(receiveCompletion: { completion in
32 | switch completion {
33 | case .finished:
34 | break
35 | case .failure(let error):
36 | XCTAssertNotNil(error.localizedDescription)
37 | }
38 | }, receiveValue: { model in
39 | expectedResults = model
40 | exception.fulfill()
41 | })
42 | XCTAssertNotNil(expectedResults)
43 | self.waitForExpectations(timeout: 1, handler: nil)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MVVM with RxSwiftUITests/MVVM_with_RxSwiftUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MVVM_with_RxSwiftUITests.swift
3 | // MVVM with RxSwiftUITests
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import XCTest
9 |
10 | class MVVM_with_RxSwiftUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Storyboard/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Hi there, This is MVVM example app with RxSwift & RxDataSources & Dependency Injection & UnitTests and more 👋
2 |
3 |
4 | 

5 |
6 |
7 | ## MVVM with RxSwift Example Features:
8 |
9 | - Real World BasicApp with MVVM and binding using RxSwift you can scale it easly.
10 | - API Calls with Combine DataTaskPublisher
11 | - Handle Error with Combine ErrorMaping.
12 | - Passing data with Combine AnyPuplisher.
13 | - Handle All App States with RxSwift Observables like loading and error.
14 | - Initializte Dependencies to ViewModel with Dependency Injection.
15 | - Advanced Sectioned TableView with RxDataSources.
16 | - Unit Tests for Usecase and ViewModel with Mocking and Stubs.
17 |
18 | ## Important Notes:
19 |
20 | - open your terminal type 'cd' and drag the project folder and type this line:
21 | ```
22 | pod install
23 | ```
24 | [contact]: https://www.linkedin.com/in/ali-fayed-8682aa1a6/
25 | [fb]: https://www.facebook.com/alifayed26/
26 | [tw]: https://www.twitter.com/Aliifayed
27 | [mail]: https://docs.google.com/document/d/1Oo4S9pl0yM4K4uewlOh7poLAmEKLbjnFelIYHxBQL7o/edit?usp=sharing
28 |
29 |
30 | ## Contact Me:
31 |
32 | [
][contact] [
][fb] [
][tw] [
][mail]
33 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Assets/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/ViewModel/UsersViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewModel.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import Foundation
9 | import Combine
10 | import RxSwift
11 | import RxCocoa
12 | import RxDataSources
13 |
14 | class UsersViewModel {
15 | var observer: AnyCancellable?
16 | let useCase: UsersUseCaseProtocol
17 | let states = States()
18 | private var usersSectionModel = [UsersSectionModel]()
19 | private let usersListSubjet = PublishSubject<[UsersSectionModel]>()
20 | var usersListObservable: Observable<[UsersSectionModel]> {
21 | return usersListSubjet
22 | }
23 | //MARK: - Initialization
24 | init(useCase: UsersUseCaseProtocol = UsersUseCase.shared) {
25 | self.useCase = useCase
26 | }
27 | //MARK: - Methods
28 | func fetchUsers() {
29 | states.loadingState.accept(true)
30 | observer = useCase.fetchUsers()?
31 | .sink(receiveCompletion: { [weak self] completion in
32 | guard let self = self else {return}
33 | switch completion {
34 | case .finished:
35 | self.states.loadingState.accept(false)
36 | case .failure(let error):
37 | self.states.errorState.accept((true, error.localizedDescription))
38 | }
39 | }, receiveValue: { [weak self] users in
40 | guard let self = self else {return}
41 | self.usersSectionModel.append(UsersSectionModel(header: "TopUsers", items: users.dropLast(25)))
42 | self.usersSectionModel.append(UsersSectionModel(header: "MiddleUsers", items: users.dropLast(28).reversed()))
43 | self.usersSectionModel.append(UsersSectionModel(header: "LastUsers", items: users.dropLast(26).reversed()))
44 | self.usersListSubjet.onNext(self.usersSectionModel)
45 | self.usersListSubjet.onCompleted()
46 | })
47 | }
48 | func tableViewDataSource() -> RxTableViewSectionedReloadDataSource {
49 | let dataSource = RxTableViewSectionedReloadDataSource(
50 | configureCell: { (_, tableView, indexPath, items) in
51 | let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
52 | cell.textLabel?.text = items.userName
53 | return cell
54 | },
55 | titleForHeaderInSection: { dataSource, sectionIndex in
56 | return dataSource[sectionIndex].header
57 | }
58 | )
59 | return dataSource
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Module/ViewController/UsersViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UsersViewController.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import UIKit
9 | import RxSwift
10 | import RxCocoa
11 |
12 | class UsersViewController: UIViewController {
13 | //MARK: - Props
14 | @IBOutlet weak var tableView: UITableView!
15 | private let refreshControl = UIRefreshControl()
16 | private var viewModel = UsersViewModel()
17 | private let bag = DisposeBag()
18 | //MARK: - LifeCycle
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | viewModel.fetchUsers()
22 | bindDataToTableView()
23 | tableViewRefreshControl()
24 | subscribeToTableViewCellSelection()
25 | subscribeToErrorBehaviour()
26 | subsribeToLoadingBehaviour()
27 | }
28 | //MARK: - TableView
29 | func bindDataToTableView() {
30 | viewModel.usersListObservable.bind(to: tableView.rx.items(dataSource: viewModel.tableViewDataSource()))
31 | .disposed(by: bag)
32 | }
33 | func subscribeToTableViewCellSelection() {
34 | Observable
35 | .zip(tableView.rx.itemSelected, tableView.rx.modelSelected(Users.self))
36 | .bind { [weak self] indexPath, users in
37 | guard let self = self else { return }
38 | self.tableView.deselectRow(at: indexPath, animated: true)
39 | print(users)
40 | }.disposed(by: bag)
41 | }
42 | func tableViewRefreshControl() {
43 | refreshControl.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)
44 | tableView.addSubview(refreshControl)
45 | }
46 | @objc func didPullToRefresh() {
47 | self.viewModel.fetchUsers()
48 | self.refreshControl.endRefreshing()
49 | }
50 | //MARK: - Loading
51 | func subsribeToLoadingBehaviour() {
52 | viewModel.states.loadingState.subscribe(onNext: { [weak self] (isLoading) in
53 | guard let self = self else { return }
54 | isLoading ? self.showIndicator(withTitle: "Loading", and: "") : self.hideIndicator()
55 | }).disposed(by: bag)
56 | }
57 | //MARK: - Error
58 | func subscribeToErrorBehaviour() {
59 | viewModel.states.errorState.subscribe(onNext: { [weak self] (error) in
60 | guard let self = self else { return }
61 | let ifResponseFailed = error.0
62 | let errorMessage = error.1
63 | if ifResponseFailed {
64 | self.alertWithOneAction(title: "Error", msg: errorMessage, btnTitle: "Ok")
65 | }
66 | }).disposed(by: bag)
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/AppDelegate/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 |
49 | // Save changes in the application's managed object context when the application transitions to the background.
50 | (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
51 | }
52 |
53 |
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/AppDelegate/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // MVVM with RxSwift
4 | //
5 | // Created by Ali Fayed on 28/11/2021.
6 | //
7 |
8 | import UIKit
9 | import CoreData
10 | import MBProgressHUD
11 |
12 | @main
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | // MARK: UISceneSession Lifecycle
23 |
24 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
25 | // Called when a new scene session is being created.
26 | // Use this method to select a configuration to create the new scene with.
27 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
28 | }
29 |
30 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
31 | // Called when the user discards a scene session.
32 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
33 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
34 | }
35 |
36 | // MARK: - Core Data stack
37 |
38 | lazy var persistentContainer: NSPersistentContainer = {
39 | /*
40 | The persistent container for the application. This implementation
41 | creates and returns a container, having loaded the store for the
42 | application to it. This property is optional since there are legitimate
43 | error conditions that could cause the creation of the store to fail.
44 | */
45 | let container = NSPersistentContainer(name: "MVVM_with_RxSwift")
46 | container.loadPersistentStores(completionHandler: { (storeDescription, error) in
47 | if let error = error as NSError? {
48 | // Replace this implementation with code to handle the error appropriately.
49 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
50 |
51 | /*
52 | Typical reasons for an error here include:
53 | * The parent directory does not exist, cannot be created, or disallows writing.
54 | * The persistent store is not accessible, due to permissions or data protection when the device is locked.
55 | * The device is out of space.
56 | * The store could not be migrated to the current model version.
57 | Check the error message to determine what the actual problem was.
58 | */
59 | fatalError("Unresolved error \(error), \(error.userInfo)")
60 | }
61 | })
62 | return container
63 | }()
64 |
65 | // MARK: - Core Data Saving support
66 |
67 | func saveContext () {
68 | let context = persistentContainer.viewContext
69 | if context.hasChanges {
70 | do {
71 | try context.save()
72 | } catch {
73 | // Replace this implementation with code to handle the error appropriately.
74 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
75 | let nserror = error as NSError
76 | fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
77 | }
78 | }
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/MVVM with RxSwift/Storyboard/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/MVVM with RxSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7E07C56160C14C25B8616872 /* Pods_MVVM_with_RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E42D610E1C65242A3294F95F /* Pods_MVVM_with_RxSwift.framework */; };
11 | B44374FE792A8842BF71DF79 /* Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1749B08B3568EB040275B022 /* Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework */; };
12 | DFF43A88339F48942BEC547E /* Pods_MVVM_with_RxSwiftTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C73F5284F547AC64A0CAD650 /* Pods_MVVM_with_RxSwiftTests.framework */; };
13 | EAD5C00B275397EE00CC2766 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C00A275397EE00CC2766 /* AppDelegate.swift */; };
14 | EAD5C00D275397EE00CC2766 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C00C275397EE00CC2766 /* SceneDelegate.swift */; };
15 | EAD5C00F275397EE00CC2766 /* UsersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C00E275397EE00CC2766 /* UsersViewController.swift */; };
16 | EAD5C012275397EE00CC2766 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EAD5C010275397EE00CC2766 /* Main.storyboard */; };
17 | EAD5C015275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C013275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodeld */; };
18 | EAD5C017275397F100CC2766 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAD5C016275397F100CC2766 /* Assets.xcassets */; };
19 | EAD5C01A275397F100CC2766 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EAD5C018275397F100CC2766 /* LaunchScreen.storyboard */; };
20 | EAD5C02F275397F200CC2766 /* MVVM_with_RxSwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C02E275397F200CC2766 /* MVVM_with_RxSwiftUITests.swift */; };
21 | EAD5C031275397F200CC2766 /* MVVM_with_RxSwiftUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C030275397F200CC2766 /* MVVM_with_RxSwiftUITestsLaunchTests.swift */; };
22 | EAD5C0422753983900CC2766 /* UsersModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0412753983900CC2766 /* UsersModel.swift */; };
23 | EAD5C0442753984400CC2766 /* UsersUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0432753984400CC2766 /* UsersUseCase.swift */; };
24 | EAD5C0462753985B00CC2766 /* UsersUseCaseProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0452753985B00CC2766 /* UsersUseCaseProtocol.swift */; };
25 | EAD5C0482753990300CC2766 /* UsersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0472753990300CC2766 /* UsersViewModel.swift */; };
26 | EAD5C04D2753AD9D00CC2766 /* Alerts+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C04C2753AD9D00CC2766 /* Alerts+Ext.swift */; };
27 | EAD5C04F2753ADAB00CC2766 /* LoadingIndicator+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C04E2753ADAB00CC2766 /* LoadingIndicator+Ext.swift */; };
28 | EAD5C0572753C5BA00CC2766 /* UsersSectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0562753C5BA00CC2766 /* UsersSectionModel.swift */; };
29 | EAD5C05A2753CE9D00CC2766 /* JSONMocking.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0592753CE9D00CC2766 /* JSONMocking.swift */; };
30 | EAD5C05C2753CEAB00CC2766 /* UsersUseCaseMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C05B2753CEAB00CC2766 /* UsersUseCaseMock.swift */; };
31 | EAD5C05E2753CEC100CC2766 /* UsersUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C05D2753CEC100CC2766 /* UsersUseCaseTests.swift */; };
32 | EAD5C0602753CECF00CC2766 /* UsersViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C05F2753CECE00CC2766 /* UsersViewModelTests.swift */; };
33 | EAD5C0622753CEE600CC2766 /* StubRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0612753CEE600CC2766 /* StubRequests.swift */; };
34 | EAD5C0642753E48400CC2766 /* States.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD5C0632753E48400CC2766 /* States.swift */; };
35 | /* End PBXBuildFile section */
36 |
37 | /* Begin PBXContainerItemProxy section */
38 | EAD5C021275397F100CC2766 /* PBXContainerItemProxy */ = {
39 | isa = PBXContainerItemProxy;
40 | containerPortal = EAD5BFFF275397EE00CC2766 /* Project object */;
41 | proxyType = 1;
42 | remoteGlobalIDString = EAD5C006275397EE00CC2766;
43 | remoteInfo = "MVVM with RxSwift";
44 | };
45 | EAD5C02B275397F200CC2766 /* PBXContainerItemProxy */ = {
46 | isa = PBXContainerItemProxy;
47 | containerPortal = EAD5BFFF275397EE00CC2766 /* Project object */;
48 | proxyType = 1;
49 | remoteGlobalIDString = EAD5C006275397EE00CC2766;
50 | remoteInfo = "MVVM with RxSwift";
51 | };
52 | /* End PBXContainerItemProxy section */
53 |
54 | /* Begin PBXFileReference section */
55 | 0388C88983F05A45E555A5BD /* Pods-MVVM with RxSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwift.debug.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwift/Pods-MVVM with RxSwift.debug.xcconfig"; sourceTree = ""; };
56 | 1749B08B3568EB040275B022 /* Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
57 | 45041708CCBF800C159CB7C3 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.debug.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.debug.xcconfig"; sourceTree = ""; };
58 | 82C2250A6F207AD6E4F7E033 /* Pods-MVVM with RxSwiftTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwiftTests.release.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwiftTests/Pods-MVVM with RxSwiftTests.release.xcconfig"; sourceTree = ""; };
59 | A5BE4870BBC3A803270463C8 /* Pods-MVVM with RxSwift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwift.release.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwift/Pods-MVVM with RxSwift.release.xcconfig"; sourceTree = ""; };
60 | ADF09A289472C810D4DFD134 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.release.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.release.xcconfig"; sourceTree = ""; };
61 | C137A675521ACEBAA19DAF49 /* Pods-MVVM with RxSwiftTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MVVM with RxSwiftTests.debug.xcconfig"; path = "Target Support Files/Pods-MVVM with RxSwiftTests/Pods-MVVM with RxSwiftTests.debug.xcconfig"; sourceTree = ""; };
62 | C73F5284F547AC64A0CAD650 /* Pods_MVVM_with_RxSwiftTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MVVM_with_RxSwiftTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
63 | E42D610E1C65242A3294F95F /* Pods_MVVM_with_RxSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MVVM_with_RxSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
64 | EAD5C007275397EE00CC2766 /* MVVM with RxSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MVVM with RxSwift.app"; sourceTree = BUILT_PRODUCTS_DIR; };
65 | EAD5C00A275397EE00CC2766 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
66 | EAD5C00C275397EE00CC2766 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
67 | EAD5C00E275397EE00CC2766 /* UsersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersViewController.swift; sourceTree = ""; };
68 | EAD5C011275397EE00CC2766 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
69 | EAD5C014275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MVVM_with_RxSwift.xcdatamodel; sourceTree = ""; };
70 | EAD5C016275397F100CC2766 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
71 | EAD5C019275397F100CC2766 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
72 | EAD5C01B275397F100CC2766 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
73 | EAD5C020275397F100CC2766 /* MVVM with RxSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MVVM with RxSwiftTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
74 | EAD5C02A275397F100CC2766 /* MVVM with RxSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MVVM with RxSwiftUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
75 | EAD5C02E275397F200CC2766 /* MVVM_with_RxSwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVVM_with_RxSwiftUITests.swift; sourceTree = ""; };
76 | EAD5C030275397F200CC2766 /* MVVM_with_RxSwiftUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVVM_with_RxSwiftUITestsLaunchTests.swift; sourceTree = ""; };
77 | EAD5C0412753983900CC2766 /* UsersModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersModel.swift; sourceTree = ""; };
78 | EAD5C0432753984400CC2766 /* UsersUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersUseCase.swift; sourceTree = ""; };
79 | EAD5C0452753985B00CC2766 /* UsersUseCaseProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersUseCaseProtocol.swift; sourceTree = ""; };
80 | EAD5C0472753990300CC2766 /* UsersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersViewModel.swift; sourceTree = ""; };
81 | EAD5C04C2753AD9D00CC2766 /* Alerts+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Alerts+Ext.swift"; sourceTree = ""; };
82 | EAD5C04E2753ADAB00CC2766 /* LoadingIndicator+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoadingIndicator+Ext.swift"; sourceTree = ""; };
83 | EAD5C0562753C5BA00CC2766 /* UsersSectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersSectionModel.swift; sourceTree = ""; };
84 | EAD5C0592753CE9D00CC2766 /* JSONMocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONMocking.swift; sourceTree = ""; };
85 | EAD5C05B2753CEAB00CC2766 /* UsersUseCaseMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersUseCaseMock.swift; sourceTree = ""; };
86 | EAD5C05D2753CEC100CC2766 /* UsersUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersUseCaseTests.swift; sourceTree = ""; };
87 | EAD5C05F2753CECE00CC2766 /* UsersViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsersViewModelTests.swift; sourceTree = ""; };
88 | EAD5C0612753CEE600CC2766 /* StubRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubRequests.swift; sourceTree = ""; };
89 | EAD5C0632753E48400CC2766 /* States.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = States.swift; sourceTree = ""; };
90 | /* End PBXFileReference section */
91 |
92 | /* Begin PBXFrameworksBuildPhase section */
93 | EAD5C004275397EE00CC2766 /* Frameworks */ = {
94 | isa = PBXFrameworksBuildPhase;
95 | buildActionMask = 2147483647;
96 | files = (
97 | 7E07C56160C14C25B8616872 /* Pods_MVVM_with_RxSwift.framework in Frameworks */,
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | EAD5C01D275397F100CC2766 /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | DFF43A88339F48942BEC547E /* Pods_MVVM_with_RxSwiftTests.framework in Frameworks */,
106 | );
107 | runOnlyForDeploymentPostprocessing = 0;
108 | };
109 | EAD5C027275397F100CC2766 /* Frameworks */ = {
110 | isa = PBXFrameworksBuildPhase;
111 | buildActionMask = 2147483647;
112 | files = (
113 | B44374FE792A8842BF71DF79 /* Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework in Frameworks */,
114 | );
115 | runOnlyForDeploymentPostprocessing = 0;
116 | };
117 | /* End PBXFrameworksBuildPhase section */
118 |
119 | /* Begin PBXGroup section */
120 | 0A9EED412A510937DEDB32FA /* Pods */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 0388C88983F05A45E555A5BD /* Pods-MVVM with RxSwift.debug.xcconfig */,
124 | A5BE4870BBC3A803270463C8 /* Pods-MVVM with RxSwift.release.xcconfig */,
125 | 45041708CCBF800C159CB7C3 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.debug.xcconfig */,
126 | ADF09A289472C810D4DFD134 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.release.xcconfig */,
127 | C137A675521ACEBAA19DAF49 /* Pods-MVVM with RxSwiftTests.debug.xcconfig */,
128 | 82C2250A6F207AD6E4F7E033 /* Pods-MVVM with RxSwiftTests.release.xcconfig */,
129 | );
130 | path = Pods;
131 | sourceTree = "";
132 | };
133 | DDD89F83DF64741DEDE4578F /* Frameworks */ = {
134 | isa = PBXGroup;
135 | children = (
136 | E42D610E1C65242A3294F95F /* Pods_MVVM_with_RxSwift.framework */,
137 | 1749B08B3568EB040275B022 /* Pods_MVVM_with_RxSwift_MVVM_with_RxSwiftUITests.framework */,
138 | C73F5284F547AC64A0CAD650 /* Pods_MVVM_with_RxSwiftTests.framework */,
139 | );
140 | name = Frameworks;
141 | sourceTree = "";
142 | };
143 | EAD5BFFE275397EE00CC2766 = {
144 | isa = PBXGroup;
145 | children = (
146 | EAD5C009275397EE00CC2766 /* MVVM with RxSwift */,
147 | EAD5C023275397F100CC2766 /* MVVM with RxSwiftTests */,
148 | EAD5C02D275397F200CC2766 /* MVVM with RxSwiftUITests */,
149 | EAD5C008275397EE00CC2766 /* Products */,
150 | 0A9EED412A510937DEDB32FA /* Pods */,
151 | DDD89F83DF64741DEDE4578F /* Frameworks */,
152 | );
153 | sourceTree = "";
154 | };
155 | EAD5C008275397EE00CC2766 /* Products */ = {
156 | isa = PBXGroup;
157 | children = (
158 | EAD5C007275397EE00CC2766 /* MVVM with RxSwift.app */,
159 | EAD5C020275397F100CC2766 /* MVVM with RxSwiftTests.xctest */,
160 | EAD5C02A275397F100CC2766 /* MVVM with RxSwiftUITests.xctest */,
161 | );
162 | name = Products;
163 | sourceTree = "";
164 | };
165 | EAD5C009275397EE00CC2766 /* MVVM with RxSwift */ = {
166 | isa = PBXGroup;
167 | children = (
168 | EAD5C03D2753980600CC2766 /* AppDelegate */,
169 | EAD5C0402753982300CC2766 /* Module */,
170 | EAD5C0652753EDD000CC2766 /* States */,
171 | EAD5C03E2753981100CC2766 /* Storyboard */,
172 | EAD5C03F2753981D00CC2766 /* Assets */,
173 | EAD5C04B2753AD8A00CC2766 /* Extentions */,
174 | EAD5C01B275397F100CC2766 /* Info.plist */,
175 | );
176 | path = "MVVM with RxSwift";
177 | sourceTree = "";
178 | };
179 | EAD5C023275397F100CC2766 /* MVVM with RxSwiftTests */ = {
180 | isa = PBXGroup;
181 | children = (
182 | EAD5C0612753CEE600CC2766 /* StubRequests.swift */,
183 | EAD5C0662753F23500CC2766 /* UsersModuleTests */,
184 | );
185 | path = "MVVM with RxSwiftTests";
186 | sourceTree = "";
187 | };
188 | EAD5C02D275397F200CC2766 /* MVVM with RxSwiftUITests */ = {
189 | isa = PBXGroup;
190 | children = (
191 | EAD5C02E275397F200CC2766 /* MVVM_with_RxSwiftUITests.swift */,
192 | EAD5C030275397F200CC2766 /* MVVM_with_RxSwiftUITestsLaunchTests.swift */,
193 | );
194 | path = "MVVM with RxSwiftUITests";
195 | sourceTree = "";
196 | };
197 | EAD5C03D2753980600CC2766 /* AppDelegate */ = {
198 | isa = PBXGroup;
199 | children = (
200 | EAD5C00A275397EE00CC2766 /* AppDelegate.swift */,
201 | EAD5C00C275397EE00CC2766 /* SceneDelegate.swift */,
202 | );
203 | path = AppDelegate;
204 | sourceTree = "";
205 | };
206 | EAD5C03E2753981100CC2766 /* Storyboard */ = {
207 | isa = PBXGroup;
208 | children = (
209 | EAD5C010275397EE00CC2766 /* Main.storyboard */,
210 | EAD5C018275397F100CC2766 /* LaunchScreen.storyboard */,
211 | );
212 | path = Storyboard;
213 | sourceTree = "";
214 | };
215 | EAD5C03F2753981D00CC2766 /* Assets */ = {
216 | isa = PBXGroup;
217 | children = (
218 | EAD5C016275397F100CC2766 /* Assets.xcassets */,
219 | EAD5C013275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodeld */,
220 | );
221 | path = Assets;
222 | sourceTree = "";
223 | };
224 | EAD5C0402753982300CC2766 /* Module */ = {
225 | isa = PBXGroup;
226 | children = (
227 | EAD5C0502753AE3100CC2766 /* Model */,
228 | EAD5C0512753AE3700CC2766 /* ViewController */,
229 | EAD5C0522753AE4700CC2766 /* ViewModel */,
230 | EAD5C0532753AE5000CC2766 /* UseCase */,
231 | );
232 | path = Module;
233 | sourceTree = "";
234 | };
235 | EAD5C04B2753AD8A00CC2766 /* Extentions */ = {
236 | isa = PBXGroup;
237 | children = (
238 | EAD5C04C2753AD9D00CC2766 /* Alerts+Ext.swift */,
239 | EAD5C04E2753ADAB00CC2766 /* LoadingIndicator+Ext.swift */,
240 | );
241 | path = Extentions;
242 | sourceTree = "";
243 | };
244 | EAD5C0502753AE3100CC2766 /* Model */ = {
245 | isa = PBXGroup;
246 | children = (
247 | EAD5C0412753983900CC2766 /* UsersModel.swift */,
248 | EAD5C0562753C5BA00CC2766 /* UsersSectionModel.swift */,
249 | );
250 | path = Model;
251 | sourceTree = "";
252 | };
253 | EAD5C0512753AE3700CC2766 /* ViewController */ = {
254 | isa = PBXGroup;
255 | children = (
256 | EAD5C00E275397EE00CC2766 /* UsersViewController.swift */,
257 | );
258 | path = ViewController;
259 | sourceTree = "";
260 | };
261 | EAD5C0522753AE4700CC2766 /* ViewModel */ = {
262 | isa = PBXGroup;
263 | children = (
264 | EAD5C0472753990300CC2766 /* UsersViewModel.swift */,
265 | );
266 | path = ViewModel;
267 | sourceTree = "";
268 | };
269 | EAD5C0532753AE5000CC2766 /* UseCase */ = {
270 | isa = PBXGroup;
271 | children = (
272 | EAD5C0432753984400CC2766 /* UsersUseCase.swift */,
273 | EAD5C0452753985B00CC2766 /* UsersUseCaseProtocol.swift */,
274 | );
275 | path = UseCase;
276 | sourceTree = "";
277 | };
278 | EAD5C0582753CE8F00CC2766 /* Stubs and Mocks */ = {
279 | isa = PBXGroup;
280 | children = (
281 | EAD5C0592753CE9D00CC2766 /* JSONMocking.swift */,
282 | EAD5C05B2753CEAB00CC2766 /* UsersUseCaseMock.swift */,
283 | );
284 | path = "Stubs and Mocks";
285 | sourceTree = "";
286 | };
287 | EAD5C0652753EDD000CC2766 /* States */ = {
288 | isa = PBXGroup;
289 | children = (
290 | EAD5C0632753E48400CC2766 /* States.swift */,
291 | );
292 | path = States;
293 | sourceTree = "";
294 | };
295 | EAD5C0662753F23500CC2766 /* UsersModuleTests */ = {
296 | isa = PBXGroup;
297 | children = (
298 | EAD5C0582753CE8F00CC2766 /* Stubs and Mocks */,
299 | EAD5C05D2753CEC100CC2766 /* UsersUseCaseTests.swift */,
300 | EAD5C05F2753CECE00CC2766 /* UsersViewModelTests.swift */,
301 | );
302 | path = UsersModuleTests;
303 | sourceTree = "";
304 | };
305 | /* End PBXGroup section */
306 |
307 | /* Begin PBXNativeTarget section */
308 | EAD5C006275397EE00CC2766 /* MVVM with RxSwift */ = {
309 | isa = PBXNativeTarget;
310 | buildConfigurationList = EAD5C034275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwift" */;
311 | buildPhases = (
312 | 5A81DC24DD1681F8D46F53F6 /* [CP] Check Pods Manifest.lock */,
313 | EAD5C003275397EE00CC2766 /* Sources */,
314 | EAD5C004275397EE00CC2766 /* Frameworks */,
315 | EAD5C005275397EE00CC2766 /* Resources */,
316 | 042BEDBBFB45D5AE6DA63C12 /* [CP] Embed Pods Frameworks */,
317 | );
318 | buildRules = (
319 | );
320 | dependencies = (
321 | );
322 | name = "MVVM with RxSwift";
323 | productName = "MVVM with RxSwift";
324 | productReference = EAD5C007275397EE00CC2766 /* MVVM with RxSwift.app */;
325 | productType = "com.apple.product-type.application";
326 | };
327 | EAD5C01F275397F100CC2766 /* MVVM with RxSwiftTests */ = {
328 | isa = PBXNativeTarget;
329 | buildConfigurationList = EAD5C037275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwiftTests" */;
330 | buildPhases = (
331 | AAE4D56B4BD0F0BABDC152BA /* [CP] Check Pods Manifest.lock */,
332 | EAD5C01C275397F100CC2766 /* Sources */,
333 | EAD5C01D275397F100CC2766 /* Frameworks */,
334 | EAD5C01E275397F100CC2766 /* Resources */,
335 | );
336 | buildRules = (
337 | );
338 | dependencies = (
339 | EAD5C022275397F100CC2766 /* PBXTargetDependency */,
340 | );
341 | name = "MVVM with RxSwiftTests";
342 | productName = "MVVM with RxSwiftTests";
343 | productReference = EAD5C020275397F100CC2766 /* MVVM with RxSwiftTests.xctest */;
344 | productType = "com.apple.product-type.bundle.unit-test";
345 | };
346 | EAD5C029275397F100CC2766 /* MVVM with RxSwiftUITests */ = {
347 | isa = PBXNativeTarget;
348 | buildConfigurationList = EAD5C03A275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwiftUITests" */;
349 | buildPhases = (
350 | BDFF3F4B87CA97A37A863EB3 /* [CP] Check Pods Manifest.lock */,
351 | EAD5C026275397F100CC2766 /* Sources */,
352 | EAD5C027275397F100CC2766 /* Frameworks */,
353 | EAD5C028275397F100CC2766 /* Resources */,
354 | 3D95BAA209DC735C17410F5B /* [CP] Embed Pods Frameworks */,
355 | );
356 | buildRules = (
357 | );
358 | dependencies = (
359 | EAD5C02C275397F200CC2766 /* PBXTargetDependency */,
360 | );
361 | name = "MVVM with RxSwiftUITests";
362 | productName = "MVVM with RxSwiftUITests";
363 | productReference = EAD5C02A275397F100CC2766 /* MVVM with RxSwiftUITests.xctest */;
364 | productType = "com.apple.product-type.bundle.ui-testing";
365 | };
366 | /* End PBXNativeTarget section */
367 |
368 | /* Begin PBXProject section */
369 | EAD5BFFF275397EE00CC2766 /* Project object */ = {
370 | isa = PBXProject;
371 | attributes = {
372 | BuildIndependentTargetsInParallel = 1;
373 | LastSwiftUpdateCheck = 1310;
374 | LastUpgradeCheck = 1310;
375 | TargetAttributes = {
376 | EAD5C006275397EE00CC2766 = {
377 | CreatedOnToolsVersion = 13.1;
378 | };
379 | EAD5C01F275397F100CC2766 = {
380 | CreatedOnToolsVersion = 13.1;
381 | TestTargetID = EAD5C006275397EE00CC2766;
382 | };
383 | EAD5C029275397F100CC2766 = {
384 | CreatedOnToolsVersion = 13.1;
385 | TestTargetID = EAD5C006275397EE00CC2766;
386 | };
387 | };
388 | };
389 | buildConfigurationList = EAD5C002275397EE00CC2766 /* Build configuration list for PBXProject "MVVM with RxSwift" */;
390 | compatibilityVersion = "Xcode 13.0";
391 | developmentRegion = en;
392 | hasScannedForEncodings = 0;
393 | knownRegions = (
394 | en,
395 | Base,
396 | );
397 | mainGroup = EAD5BFFE275397EE00CC2766;
398 | productRefGroup = EAD5C008275397EE00CC2766 /* Products */;
399 | projectDirPath = "";
400 | projectRoot = "";
401 | targets = (
402 | EAD5C006275397EE00CC2766 /* MVVM with RxSwift */,
403 | EAD5C01F275397F100CC2766 /* MVVM with RxSwiftTests */,
404 | EAD5C029275397F100CC2766 /* MVVM with RxSwiftUITests */,
405 | );
406 | };
407 | /* End PBXProject section */
408 |
409 | /* Begin PBXResourcesBuildPhase section */
410 | EAD5C005275397EE00CC2766 /* Resources */ = {
411 | isa = PBXResourcesBuildPhase;
412 | buildActionMask = 2147483647;
413 | files = (
414 | EAD5C01A275397F100CC2766 /* LaunchScreen.storyboard in Resources */,
415 | EAD5C017275397F100CC2766 /* Assets.xcassets in Resources */,
416 | EAD5C012275397EE00CC2766 /* Main.storyboard in Resources */,
417 | );
418 | runOnlyForDeploymentPostprocessing = 0;
419 | };
420 | EAD5C01E275397F100CC2766 /* Resources */ = {
421 | isa = PBXResourcesBuildPhase;
422 | buildActionMask = 2147483647;
423 | files = (
424 | );
425 | runOnlyForDeploymentPostprocessing = 0;
426 | };
427 | EAD5C028275397F100CC2766 /* Resources */ = {
428 | isa = PBXResourcesBuildPhase;
429 | buildActionMask = 2147483647;
430 | files = (
431 | );
432 | runOnlyForDeploymentPostprocessing = 0;
433 | };
434 | /* End PBXResourcesBuildPhase section */
435 |
436 | /* Begin PBXShellScriptBuildPhase section */
437 | 042BEDBBFB45D5AE6DA63C12 /* [CP] Embed Pods Frameworks */ = {
438 | isa = PBXShellScriptBuildPhase;
439 | buildActionMask = 2147483647;
440 | files = (
441 | );
442 | inputFileListPaths = (
443 | "${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift/Pods-MVVM with RxSwift-frameworks-${CONFIGURATION}-input-files.xcfilelist",
444 | );
445 | name = "[CP] Embed Pods Frameworks";
446 | outputFileListPaths = (
447 | "${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift/Pods-MVVM with RxSwift-frameworks-${CONFIGURATION}-output-files.xcfilelist",
448 | );
449 | runOnlyForDeploymentPostprocessing = 0;
450 | shellPath = /bin/sh;
451 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift/Pods-MVVM with RxSwift-frameworks.sh\"\n";
452 | showEnvVarsInLog = 0;
453 | };
454 | 3D95BAA209DC735C17410F5B /* [CP] Embed Pods Frameworks */ = {
455 | isa = PBXShellScriptBuildPhase;
456 | buildActionMask = 2147483647;
457 | files = (
458 | );
459 | inputFileListPaths = (
460 | "${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
461 | );
462 | name = "[CP] Embed Pods Frameworks";
463 | outputFileListPaths = (
464 | "${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
465 | );
466 | runOnlyForDeploymentPostprocessing = 0;
467 | shellPath = /bin/sh;
468 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests-frameworks.sh\"\n";
469 | showEnvVarsInLog = 0;
470 | };
471 | 5A81DC24DD1681F8D46F53F6 /* [CP] Check Pods Manifest.lock */ = {
472 | isa = PBXShellScriptBuildPhase;
473 | buildActionMask = 2147483647;
474 | files = (
475 | );
476 | inputFileListPaths = (
477 | );
478 | inputPaths = (
479 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
480 | "${PODS_ROOT}/Manifest.lock",
481 | );
482 | name = "[CP] Check Pods Manifest.lock";
483 | outputFileListPaths = (
484 | );
485 | outputPaths = (
486 | "$(DERIVED_FILE_DIR)/Pods-MVVM with RxSwift-checkManifestLockResult.txt",
487 | );
488 | runOnlyForDeploymentPostprocessing = 0;
489 | shellPath = /bin/sh;
490 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
491 | showEnvVarsInLog = 0;
492 | };
493 | AAE4D56B4BD0F0BABDC152BA /* [CP] Check Pods Manifest.lock */ = {
494 | isa = PBXShellScriptBuildPhase;
495 | buildActionMask = 2147483647;
496 | files = (
497 | );
498 | inputFileListPaths = (
499 | );
500 | inputPaths = (
501 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
502 | "${PODS_ROOT}/Manifest.lock",
503 | );
504 | name = "[CP] Check Pods Manifest.lock";
505 | outputFileListPaths = (
506 | );
507 | outputPaths = (
508 | "$(DERIVED_FILE_DIR)/Pods-MVVM with RxSwiftTests-checkManifestLockResult.txt",
509 | );
510 | runOnlyForDeploymentPostprocessing = 0;
511 | shellPath = /bin/sh;
512 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
513 | showEnvVarsInLog = 0;
514 | };
515 | BDFF3F4B87CA97A37A863EB3 /* [CP] Check Pods Manifest.lock */ = {
516 | isa = PBXShellScriptBuildPhase;
517 | buildActionMask = 2147483647;
518 | files = (
519 | );
520 | inputFileListPaths = (
521 | );
522 | inputPaths = (
523 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
524 | "${PODS_ROOT}/Manifest.lock",
525 | );
526 | name = "[CP] Check Pods Manifest.lock";
527 | outputFileListPaths = (
528 | );
529 | outputPaths = (
530 | "$(DERIVED_FILE_DIR)/Pods-MVVM with RxSwift-MVVM with RxSwiftUITests-checkManifestLockResult.txt",
531 | );
532 | runOnlyForDeploymentPostprocessing = 0;
533 | shellPath = /bin/sh;
534 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
535 | showEnvVarsInLog = 0;
536 | };
537 | /* End PBXShellScriptBuildPhase section */
538 |
539 | /* Begin PBXSourcesBuildPhase section */
540 | EAD5C003275397EE00CC2766 /* Sources */ = {
541 | isa = PBXSourcesBuildPhase;
542 | buildActionMask = 2147483647;
543 | files = (
544 | EAD5C04F2753ADAB00CC2766 /* LoadingIndicator+Ext.swift in Sources */,
545 | EAD5C0422753983900CC2766 /* UsersModel.swift in Sources */,
546 | EAD5C04D2753AD9D00CC2766 /* Alerts+Ext.swift in Sources */,
547 | EAD5C0642753E48400CC2766 /* States.swift in Sources */,
548 | EAD5C00F275397EE00CC2766 /* UsersViewController.swift in Sources */,
549 | EAD5C015275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodeld in Sources */,
550 | EAD5C0442753984400CC2766 /* UsersUseCase.swift in Sources */,
551 | EAD5C00B275397EE00CC2766 /* AppDelegate.swift in Sources */,
552 | EAD5C00D275397EE00CC2766 /* SceneDelegate.swift in Sources */,
553 | EAD5C0572753C5BA00CC2766 /* UsersSectionModel.swift in Sources */,
554 | EAD5C0482753990300CC2766 /* UsersViewModel.swift in Sources */,
555 | EAD5C0462753985B00CC2766 /* UsersUseCaseProtocol.swift in Sources */,
556 | );
557 | runOnlyForDeploymentPostprocessing = 0;
558 | };
559 | EAD5C01C275397F100CC2766 /* Sources */ = {
560 | isa = PBXSourcesBuildPhase;
561 | buildActionMask = 2147483647;
562 | files = (
563 | EAD5C05A2753CE9D00CC2766 /* JSONMocking.swift in Sources */,
564 | EAD5C05E2753CEC100CC2766 /* UsersUseCaseTests.swift in Sources */,
565 | EAD5C0602753CECF00CC2766 /* UsersViewModelTests.swift in Sources */,
566 | EAD5C0622753CEE600CC2766 /* StubRequests.swift in Sources */,
567 | EAD5C05C2753CEAB00CC2766 /* UsersUseCaseMock.swift in Sources */,
568 | );
569 | runOnlyForDeploymentPostprocessing = 0;
570 | };
571 | EAD5C026275397F100CC2766 /* Sources */ = {
572 | isa = PBXSourcesBuildPhase;
573 | buildActionMask = 2147483647;
574 | files = (
575 | EAD5C031275397F200CC2766 /* MVVM_with_RxSwiftUITestsLaunchTests.swift in Sources */,
576 | EAD5C02F275397F200CC2766 /* MVVM_with_RxSwiftUITests.swift in Sources */,
577 | );
578 | runOnlyForDeploymentPostprocessing = 0;
579 | };
580 | /* End PBXSourcesBuildPhase section */
581 |
582 | /* Begin PBXTargetDependency section */
583 | EAD5C022275397F100CC2766 /* PBXTargetDependency */ = {
584 | isa = PBXTargetDependency;
585 | target = EAD5C006275397EE00CC2766 /* MVVM with RxSwift */;
586 | targetProxy = EAD5C021275397F100CC2766 /* PBXContainerItemProxy */;
587 | };
588 | EAD5C02C275397F200CC2766 /* PBXTargetDependency */ = {
589 | isa = PBXTargetDependency;
590 | target = EAD5C006275397EE00CC2766 /* MVVM with RxSwift */;
591 | targetProxy = EAD5C02B275397F200CC2766 /* PBXContainerItemProxy */;
592 | };
593 | /* End PBXTargetDependency section */
594 |
595 | /* Begin PBXVariantGroup section */
596 | EAD5C010275397EE00CC2766 /* Main.storyboard */ = {
597 | isa = PBXVariantGroup;
598 | children = (
599 | EAD5C011275397EE00CC2766 /* Base */,
600 | );
601 | name = Main.storyboard;
602 | sourceTree = "";
603 | };
604 | EAD5C018275397F100CC2766 /* LaunchScreen.storyboard */ = {
605 | isa = PBXVariantGroup;
606 | children = (
607 | EAD5C019275397F100CC2766 /* Base */,
608 | );
609 | name = LaunchScreen.storyboard;
610 | sourceTree = "";
611 | };
612 | /* End PBXVariantGroup section */
613 |
614 | /* Begin XCBuildConfiguration section */
615 | EAD5C032275397F200CC2766 /* Debug */ = {
616 | isa = XCBuildConfiguration;
617 | buildSettings = {
618 | ALWAYS_SEARCH_USER_PATHS = NO;
619 | CLANG_ANALYZER_NONNULL = YES;
620 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
621 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
622 | CLANG_CXX_LIBRARY = "libc++";
623 | CLANG_ENABLE_MODULES = YES;
624 | CLANG_ENABLE_OBJC_ARC = YES;
625 | CLANG_ENABLE_OBJC_WEAK = YES;
626 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
627 | CLANG_WARN_BOOL_CONVERSION = YES;
628 | CLANG_WARN_COMMA = YES;
629 | CLANG_WARN_CONSTANT_CONVERSION = YES;
630 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
631 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
632 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
633 | CLANG_WARN_EMPTY_BODY = YES;
634 | CLANG_WARN_ENUM_CONVERSION = YES;
635 | CLANG_WARN_INFINITE_RECURSION = YES;
636 | CLANG_WARN_INT_CONVERSION = YES;
637 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
638 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
639 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
640 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
641 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
642 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
643 | CLANG_WARN_STRICT_PROTOTYPES = YES;
644 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
645 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
646 | CLANG_WARN_UNREACHABLE_CODE = YES;
647 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
648 | COPY_PHASE_STRIP = NO;
649 | DEBUG_INFORMATION_FORMAT = dwarf;
650 | ENABLE_STRICT_OBJC_MSGSEND = YES;
651 | ENABLE_TESTABILITY = YES;
652 | GCC_C_LANGUAGE_STANDARD = gnu11;
653 | GCC_DYNAMIC_NO_PIC = NO;
654 | GCC_NO_COMMON_BLOCKS = YES;
655 | GCC_OPTIMIZATION_LEVEL = 0;
656 | GCC_PREPROCESSOR_DEFINITIONS = (
657 | "DEBUG=1",
658 | "$(inherited)",
659 | );
660 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
661 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
662 | GCC_WARN_UNDECLARED_SELECTOR = YES;
663 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
664 | GCC_WARN_UNUSED_FUNCTION = YES;
665 | GCC_WARN_UNUSED_VARIABLE = YES;
666 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
667 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
668 | MTL_FAST_MATH = YES;
669 | ONLY_ACTIVE_ARCH = YES;
670 | SDKROOT = iphoneos;
671 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
672 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
673 | };
674 | name = Debug;
675 | };
676 | EAD5C033275397F200CC2766 /* Release */ = {
677 | isa = XCBuildConfiguration;
678 | buildSettings = {
679 | ALWAYS_SEARCH_USER_PATHS = NO;
680 | CLANG_ANALYZER_NONNULL = YES;
681 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
682 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
683 | CLANG_CXX_LIBRARY = "libc++";
684 | CLANG_ENABLE_MODULES = YES;
685 | CLANG_ENABLE_OBJC_ARC = YES;
686 | CLANG_ENABLE_OBJC_WEAK = YES;
687 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
688 | CLANG_WARN_BOOL_CONVERSION = YES;
689 | CLANG_WARN_COMMA = YES;
690 | CLANG_WARN_CONSTANT_CONVERSION = YES;
691 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
692 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
693 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
694 | CLANG_WARN_EMPTY_BODY = YES;
695 | CLANG_WARN_ENUM_CONVERSION = YES;
696 | CLANG_WARN_INFINITE_RECURSION = YES;
697 | CLANG_WARN_INT_CONVERSION = YES;
698 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
699 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
700 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
701 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
702 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
703 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
704 | CLANG_WARN_STRICT_PROTOTYPES = YES;
705 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
706 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
707 | CLANG_WARN_UNREACHABLE_CODE = YES;
708 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
709 | COPY_PHASE_STRIP = NO;
710 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
711 | ENABLE_NS_ASSERTIONS = NO;
712 | ENABLE_STRICT_OBJC_MSGSEND = YES;
713 | GCC_C_LANGUAGE_STANDARD = gnu11;
714 | GCC_NO_COMMON_BLOCKS = YES;
715 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
716 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
717 | GCC_WARN_UNDECLARED_SELECTOR = YES;
718 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
719 | GCC_WARN_UNUSED_FUNCTION = YES;
720 | GCC_WARN_UNUSED_VARIABLE = YES;
721 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
722 | MTL_ENABLE_DEBUG_INFO = NO;
723 | MTL_FAST_MATH = YES;
724 | SDKROOT = iphoneos;
725 | SWIFT_COMPILATION_MODE = wholemodule;
726 | SWIFT_OPTIMIZATION_LEVEL = "-O";
727 | VALIDATE_PRODUCT = YES;
728 | };
729 | name = Release;
730 | };
731 | EAD5C035275397F200CC2766 /* Debug */ = {
732 | isa = XCBuildConfiguration;
733 | baseConfigurationReference = 0388C88983F05A45E555A5BD /* Pods-MVVM with RxSwift.debug.xcconfig */;
734 | buildSettings = {
735 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
736 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
737 | CODE_SIGN_STYLE = Automatic;
738 | CURRENT_PROJECT_VERSION = 1;
739 | DEVELOPMENT_TEAM = H368HQSP2D;
740 | GENERATE_INFOPLIST_FILE = YES;
741 | INFOPLIST_FILE = "MVVM with RxSwift/Info.plist";
742 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
743 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
744 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
745 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
746 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
747 | LD_RUNPATH_SEARCH_PATHS = (
748 | "$(inherited)",
749 | "@executable_path/Frameworks",
750 | );
751 | MARKETING_VERSION = 1.0;
752 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwift";
753 | PRODUCT_NAME = "$(TARGET_NAME)";
754 | SWIFT_EMIT_LOC_STRINGS = YES;
755 | SWIFT_VERSION = 5.0;
756 | TARGETED_DEVICE_FAMILY = "1,2";
757 | };
758 | name = Debug;
759 | };
760 | EAD5C036275397F200CC2766 /* Release */ = {
761 | isa = XCBuildConfiguration;
762 | baseConfigurationReference = A5BE4870BBC3A803270463C8 /* Pods-MVVM with RxSwift.release.xcconfig */;
763 | buildSettings = {
764 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
765 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
766 | CODE_SIGN_STYLE = Automatic;
767 | CURRENT_PROJECT_VERSION = 1;
768 | DEVELOPMENT_TEAM = H368HQSP2D;
769 | GENERATE_INFOPLIST_FILE = YES;
770 | INFOPLIST_FILE = "MVVM with RxSwift/Info.plist";
771 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
772 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
773 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
774 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
775 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
776 | LD_RUNPATH_SEARCH_PATHS = (
777 | "$(inherited)",
778 | "@executable_path/Frameworks",
779 | );
780 | MARKETING_VERSION = 1.0;
781 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwift";
782 | PRODUCT_NAME = "$(TARGET_NAME)";
783 | SWIFT_EMIT_LOC_STRINGS = YES;
784 | SWIFT_VERSION = 5.0;
785 | TARGETED_DEVICE_FAMILY = "1,2";
786 | };
787 | name = Release;
788 | };
789 | EAD5C038275397F200CC2766 /* Debug */ = {
790 | isa = XCBuildConfiguration;
791 | baseConfigurationReference = C137A675521ACEBAA19DAF49 /* Pods-MVVM with RxSwiftTests.debug.xcconfig */;
792 | buildSettings = {
793 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
794 | BUNDLE_LOADER = "$(TEST_HOST)";
795 | CODE_SIGN_STYLE = Automatic;
796 | CURRENT_PROJECT_VERSION = 1;
797 | DEVELOPMENT_TEAM = H368HQSP2D;
798 | GENERATE_INFOPLIST_FILE = YES;
799 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
800 | LD_RUNPATH_SEARCH_PATHS = (
801 | "$(inherited)",
802 | "@executable_path/Frameworks",
803 | "@loader_path/Frameworks",
804 | );
805 | MARKETING_VERSION = 1.0;
806 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwiftTests";
807 | PRODUCT_NAME = "$(TARGET_NAME)";
808 | SWIFT_EMIT_LOC_STRINGS = NO;
809 | SWIFT_VERSION = 5.0;
810 | TARGETED_DEVICE_FAMILY = "1,2";
811 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MVVM with RxSwift.app/MVVM with RxSwift";
812 | };
813 | name = Debug;
814 | };
815 | EAD5C039275397F200CC2766 /* Release */ = {
816 | isa = XCBuildConfiguration;
817 | baseConfigurationReference = 82C2250A6F207AD6E4F7E033 /* Pods-MVVM with RxSwiftTests.release.xcconfig */;
818 | buildSettings = {
819 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
820 | BUNDLE_LOADER = "$(TEST_HOST)";
821 | CODE_SIGN_STYLE = Automatic;
822 | CURRENT_PROJECT_VERSION = 1;
823 | DEVELOPMENT_TEAM = H368HQSP2D;
824 | GENERATE_INFOPLIST_FILE = YES;
825 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
826 | LD_RUNPATH_SEARCH_PATHS = (
827 | "$(inherited)",
828 | "@executable_path/Frameworks",
829 | "@loader_path/Frameworks",
830 | );
831 | MARKETING_VERSION = 1.0;
832 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwiftTests";
833 | PRODUCT_NAME = "$(TARGET_NAME)";
834 | SWIFT_EMIT_LOC_STRINGS = NO;
835 | SWIFT_VERSION = 5.0;
836 | TARGETED_DEVICE_FAMILY = "1,2";
837 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MVVM with RxSwift.app/MVVM with RxSwift";
838 | };
839 | name = Release;
840 | };
841 | EAD5C03B275397F200CC2766 /* Debug */ = {
842 | isa = XCBuildConfiguration;
843 | baseConfigurationReference = 45041708CCBF800C159CB7C3 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.debug.xcconfig */;
844 | buildSettings = {
845 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
846 | CODE_SIGN_STYLE = Automatic;
847 | CURRENT_PROJECT_VERSION = 1;
848 | DEVELOPMENT_TEAM = H368HQSP2D;
849 | GENERATE_INFOPLIST_FILE = YES;
850 | LD_RUNPATH_SEARCH_PATHS = (
851 | "$(inherited)",
852 | "@executable_path/Frameworks",
853 | "@loader_path/Frameworks",
854 | );
855 | MARKETING_VERSION = 1.0;
856 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwiftUITests";
857 | PRODUCT_NAME = "$(TARGET_NAME)";
858 | SWIFT_EMIT_LOC_STRINGS = NO;
859 | SWIFT_VERSION = 5.0;
860 | TARGETED_DEVICE_FAMILY = "1,2";
861 | TEST_TARGET_NAME = "MVVM with RxSwift";
862 | };
863 | name = Debug;
864 | };
865 | EAD5C03C275397F200CC2766 /* Release */ = {
866 | isa = XCBuildConfiguration;
867 | baseConfigurationReference = ADF09A289472C810D4DFD134 /* Pods-MVVM with RxSwift-MVVM with RxSwiftUITests.release.xcconfig */;
868 | buildSettings = {
869 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
870 | CODE_SIGN_STYLE = Automatic;
871 | CURRENT_PROJECT_VERSION = 1;
872 | DEVELOPMENT_TEAM = H368HQSP2D;
873 | GENERATE_INFOPLIST_FILE = YES;
874 | LD_RUNPATH_SEARCH_PATHS = (
875 | "$(inherited)",
876 | "@executable_path/Frameworks",
877 | "@loader_path/Frameworks",
878 | );
879 | MARKETING_VERSION = 1.0;
880 | PRODUCT_BUNDLE_IDENTIFIER = "com.product.MVVM-with-RxSwiftUITests";
881 | PRODUCT_NAME = "$(TARGET_NAME)";
882 | SWIFT_EMIT_LOC_STRINGS = NO;
883 | SWIFT_VERSION = 5.0;
884 | TARGETED_DEVICE_FAMILY = "1,2";
885 | TEST_TARGET_NAME = "MVVM with RxSwift";
886 | };
887 | name = Release;
888 | };
889 | /* End XCBuildConfiguration section */
890 |
891 | /* Begin XCConfigurationList section */
892 | EAD5C002275397EE00CC2766 /* Build configuration list for PBXProject "MVVM with RxSwift" */ = {
893 | isa = XCConfigurationList;
894 | buildConfigurations = (
895 | EAD5C032275397F200CC2766 /* Debug */,
896 | EAD5C033275397F200CC2766 /* Release */,
897 | );
898 | defaultConfigurationIsVisible = 0;
899 | defaultConfigurationName = Release;
900 | };
901 | EAD5C034275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwift" */ = {
902 | isa = XCConfigurationList;
903 | buildConfigurations = (
904 | EAD5C035275397F200CC2766 /* Debug */,
905 | EAD5C036275397F200CC2766 /* Release */,
906 | );
907 | defaultConfigurationIsVisible = 0;
908 | defaultConfigurationName = Release;
909 | };
910 | EAD5C037275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwiftTests" */ = {
911 | isa = XCConfigurationList;
912 | buildConfigurations = (
913 | EAD5C038275397F200CC2766 /* Debug */,
914 | EAD5C039275397F200CC2766 /* Release */,
915 | );
916 | defaultConfigurationIsVisible = 0;
917 | defaultConfigurationName = Release;
918 | };
919 | EAD5C03A275397F200CC2766 /* Build configuration list for PBXNativeTarget "MVVM with RxSwiftUITests" */ = {
920 | isa = XCConfigurationList;
921 | buildConfigurations = (
922 | EAD5C03B275397F200CC2766 /* Debug */,
923 | EAD5C03C275397F200CC2766 /* Release */,
924 | );
925 | defaultConfigurationIsVisible = 0;
926 | defaultConfigurationName = Release;
927 | };
928 | /* End XCConfigurationList section */
929 |
930 | /* Begin XCVersionGroup section */
931 | EAD5C013275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodeld */ = {
932 | isa = XCVersionGroup;
933 | children = (
934 | EAD5C014275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodel */,
935 | );
936 | currentVersion = EAD5C014275397EE00CC2766 /* MVVM_with_RxSwift.xcdatamodel */;
937 | path = MVVM_with_RxSwift.xcdatamodeld;
938 | sourceTree = "";
939 | versionGroupType = wrapper.xcdatamodel;
940 | };
941 | /* End XCVersionGroup section */
942 | };
943 | rootObject = EAD5BFFF275397EE00CC2766 /* Project object */;
944 | }
945 |
--------------------------------------------------------------------------------