Skip to content

Commit

Permalink
Merge pull request #63 from boostcampwm-2022/feature/BrowseUseCase
Browse files Browse the repository at this point in the history
Feature/browse use case, viewModel
  • Loading branch information
jinwoong16 committed Nov 30, 2022
2 parents 4c8ae2b + a87458a commit 5d38779
Show file tree
Hide file tree
Showing 15 changed files with 410 additions and 41 deletions.
82 changes: 80 additions & 2 deletions DailyQuest/DailyQuest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
3416FC93292B59D300B504C5 /* QuestRepositoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3416FC92292B59D300B504C5 /* QuestRepositoryMock.swift */; };
3416FC95292B5AD600B504C5 /* QuestUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3416FC94292B5AD600B504C5 /* QuestUseCaseTests.swift */; };
3416FC96292B5B5400B504C5 /* Quest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449AD5A2922164B00B87619 /* Quest.swift */; };
3417B1442935DA4A00900454 /* BrowseUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3417B1432935DA4A00900454 /* BrowseUseCase.swift */; };
3417B1462935DA9D00900454 /* DefaultBrowseUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3417B1452935DA9D00900454 /* DefaultBrowseUseCase.swift */; };
342830A8292E0FAC00AE811B /* SettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342830A7292E0FAC00AE811B /* SettingsCoordinator.swift */; };
342830AA292E12C700AE811B /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342830A9292E12C700AE811B /* SettingsViewController.swift */; };
342830F2292E196E00AE811B /* CommonField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342830F1292E196E00AE811B /* CommonField.swift */; };
Expand Down Expand Up @@ -82,6 +84,19 @@
34EC71CE292DEFBF004813CB /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 34EC71CD292DEFBF004813CB /* Lottie */; };
34EC71D0292DF0B5004813CB /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 34EC71CF292DF0B5004813CB /* GoogleService-Info.plist */; };
34EC71D1292DF27E004813CB /* Date+.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50F9A3829266FD8005C00FE /* Date+.swift */; };
34EE0C542935F8F7002BEC23 /* BrowseQuest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51F01D9292345990031ECA2 /* BrowseQuest.swift */; };
34EE0C562935F944002BEC23 /* BrowseQuest+Stub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C552935F944002BEC23 /* BrowseQuest+Stub.swift */; };
34EE0C572935F97E002BEC23 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449AD5C2922197000B87619 /* User.swift */; };
34EE0C592935F98D002BEC23 /* User+Stub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C582935F98D002BEC23 /* User+Stub.swift */; };
34EE0C5B2935FA2E002BEC23 /* BrowseRepositoryMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C5A2935FA2E002BEC23 /* BrowseRepositoryMock.swift */; };
34EE0C5C2935FA4C002BEC23 /* BrowseUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3417B1432935DA4A00900454 /* BrowseUseCase.swift */; };
34EE0C5D2935FA6E002BEC23 /* BrowseRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D8360029359C8A001DE9DF /* BrowseRepository.swift */; };
34EE0C5F2935FBA1002BEC23 /* BrowseUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C5E2935FBA1002BEC23 /* BrowseUseCaseTests.swift */; };
34EE0C602935FC47002BEC23 /* DefaultBrowseUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3417B1452935DA9D00900454 /* DefaultBrowseUseCase.swift */; };
34EE0C622935FD0C002BEC23 /* BrowseUseCaseMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C612935FD0C002BEC23 /* BrowseUseCaseMock.swift */; };
34EE0C642935FD6B002BEC23 /* BrowseViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE0C632935FD6B002BEC23 /* BrowseViewModelTests.swift */; };
34EE0C652935FD79002BEC23 /* BrowseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3499552A29236041007AB99E /* BrowseViewModel.swift */; };
34EE0C662935FD7D002BEC23 /* BrowseItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3499552629235D1E007AB99E /* BrowseItemViewModel.swift */; };
34EE6EB72924C674005AF583 /* QuestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE6EB62924C674005AF583 /* QuestView.swift */; };
34EE6EB92924CAA1005AF583 /* QuestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE6EB82924CAA1005AF583 /* QuestViewModel.swift */; };
34FEFB992935EA6D00954A40 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 34FEFB982935EA6D00954A40 /* Kingfisher */; };
Expand Down Expand Up @@ -163,6 +178,8 @@
3416FC8D292B593C00B504C5 /* Quest+Stub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Quest+Stub.swift"; sourceTree = "<group>"; };
3416FC92292B59D300B504C5 /* QuestRepositoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestRepositoryMock.swift; sourceTree = "<group>"; };
3416FC94292B5AD600B504C5 /* QuestUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestUseCaseTests.swift; sourceTree = "<group>"; };
3417B1432935DA4A00900454 /* BrowseUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseUseCase.swift; sourceTree = "<group>"; };
3417B1452935DA9D00900454 /* DefaultBrowseUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBrowseUseCase.swift; sourceTree = "<group>"; };
342830A7292E0FAC00AE811B /* SettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinator.swift; sourceTree = "<group>"; };
342830A9292E12C700AE811B /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
342830F1292E196E00AE811B /* CommonField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonField.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -216,6 +233,12 @@
34CAE317292B19A3007653AD /* QuestsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestsRepository.swift; sourceTree = "<group>"; };
34D8360029359C8A001DE9DF /* BrowseRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseRepository.swift; sourceTree = "<group>"; };
34EC71CF292DF0B5004813CB /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
34EE0C552935F944002BEC23 /* BrowseQuest+Stub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowseQuest+Stub.swift"; sourceTree = "<group>"; };
34EE0C582935F98D002BEC23 /* User+Stub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "User+Stub.swift"; sourceTree = "<group>"; };
34EE0C5A2935FA2E002BEC23 /* BrowseRepositoryMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseRepositoryMock.swift; sourceTree = "<group>"; };
34EE0C5E2935FBA1002BEC23 /* BrowseUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseUseCaseTests.swift; sourceTree = "<group>"; };
34EE0C612935FD0C002BEC23 /* BrowseUseCaseMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseUseCaseMock.swift; sourceTree = "<group>"; };
34EE0C632935FD6B002BEC23 /* BrowseViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowseViewModelTests.swift; sourceTree = "<group>"; };
34EE6EB62924C674005AF583 /* QuestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestView.swift; sourceTree = "<group>"; };
34EE6EB82924CAA1005AF583 /* QuestViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestViewModel.swift; sourceTree = "<group>"; };
9B1CFB3E292B585700CCE97A /* QuestDTO+Mapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "QuestDTO+Mapping.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -296,6 +319,7 @@
isa = PBXGroup;
children = (
340FDFDA292B7A1500C4E3DC /* QuestViewModelTests.swift */,
34EE0C632935FD6B002BEC23 /* BrowseViewModelTests.swift */,
);
path = ViewModel;
sourceTree = "<group>";
Expand All @@ -304,6 +328,7 @@
isa = PBXGroup;
children = (
340FDFDD292B7A2C00C4E3DC /* QuestUseCaseMock.swift */,
34EE0C612935FD0C002BEC23 /* BrowseUseCaseMock.swift */,
);
path = Mocks;
sourceTree = "<group>";
Expand All @@ -321,7 +346,6 @@
children = (
3416FC86292B54BF00B504C5 /* Protocols */,
3416FC89292B560800B504C5 /* DefaultQuestUseCase.swift */,
340A724A29348C2200B26AA6 /* DefaultAuthUseCase.swift */,
);
path = Home;
sourceTree = "<group>";
Expand All @@ -330,7 +354,6 @@
isa = PBXGroup;
children = (
3416FC87292B54DB00B504C5 /* QuestUseCase.swift */,
340A724829348B1B00B26AA6 /* AuthUseCase.swift */,
);
path = Protocols;
sourceTree = "<group>";
Expand All @@ -348,6 +371,8 @@
isa = PBXGroup;
children = (
3416FC8D292B593C00B504C5 /* Quest+Stub.swift */,
34EE0C552935F944002BEC23 /* BrowseQuest+Stub.swift */,
34EE0C582935F98D002BEC23 /* User+Stub.swift */,
);
path = Mocks;
sourceTree = "<group>";
Expand All @@ -356,6 +381,7 @@
isa = PBXGroup;
children = (
3416FC94292B5AD600B504C5 /* QuestUseCaseTests.swift */,
34EE0C5E2935FBA1002BEC23 /* BrowseUseCaseTests.swift */,
);
path = UseCases;
sourceTree = "<group>";
Expand All @@ -364,10 +390,44 @@
isa = PBXGroup;
children = (
3416FC92292B59D300B504C5 /* QuestRepositoryMock.swift */,
34EE0C5A2935FA2E002BEC23 /* BrowseRepositoryMock.swift */,
);
path = Mocks;
sourceTree = "<group>";
};
3417B13F2935DA1500900454 /* Browse */ = {
isa = PBXGroup;
children = (
3417B1412935DA2400900454 /* Protocols */,
3417B1452935DA9D00900454 /* DefaultBrowseUseCase.swift */,
);
path = Browse;
sourceTree = "<group>";
};
3417B1402935DA1B00900454 /* Settings */ = {
isa = PBXGroup;
children = (
3417B1422935DA2E00900454 /* Protocols */,
);
path = Settings;
sourceTree = "<group>";
};
3417B1412935DA2400900454 /* Protocols */ = {
isa = PBXGroup;
children = (
3417B1432935DA4A00900454 /* BrowseUseCase.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
3417B1422935DA2E00900454 /* Protocols */ = {
isa = PBXGroup;
children = (
340A724829348B1B00B26AA6 /* AuthUseCase.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
342830A5292E0F8600AE811B /* ViewController */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -482,6 +542,9 @@
34995516292329F4007AB99E /* UseCases */ = {
isa = PBXGroup;
children = (
3417B1402935DA1B00900454 /* Settings */,
340A724A29348C2200B26AA6 /* DefaultAuthUseCase.swift */,
3417B13F2935DA1500900454 /* Browse */,
3416FC85292B549900B504C5 /* Home */,
);
path = UseCases;
Expand Down Expand Up @@ -1053,6 +1116,7 @@
A50F9A3F292679BC005C00FE /* NetworkConfigure.swift in Sources */,
34A529E7292481E1001BAD34 /* BrowseCoordinator.swift in Sources */,
34A529D329247903001BAD34 /* TabCoordinator.swift in Sources */,
3417B1462935DA9D00900454 /* DefaultBrowseUseCase.swift in Sources */,
347D258D292C6E220038FCA2 /* MessageBubble.swift in Sources */,
34EE6EB92924CAA1005AF583 /* QuestViewModel.swift in Sources */,
A5656459292BBDD40033E763 /* String+.swift in Sources */,
Expand Down Expand Up @@ -1091,6 +1155,7 @@
A50DE906292B53D900E1FD60 /* DefaultQuestsRepository.swift in Sources */,
34ACC32D291DE9C000741371 /* AppDelegate.swift in Sources */,
A5AC96D929223648003B7637 /* RealmStorage.swift in Sources */,
3417B1442935DA4A00900454 /* BrowseUseCase.swift in Sources */,
A51189C329226E66008A9D33 /* QuestEntity+Mapping.swift in Sources */,
A51F01D3292340360031ECA2 /* BrowseQuestsStorage.swift in Sources */,
A50F9A3729266F6F005C00FE /* FirebaseService.swift in Sources */,
Expand Down Expand Up @@ -1124,15 +1189,28 @@
A5656457292BB91F0033E763 /* Quest.swift in Sources */,
3416FC96292B5B5400B504C5 /* Quest.swift in Sources */,
3416FC95292B5AD600B504C5 /* QuestUseCaseTests.swift in Sources */,
34EE0C572935F97E002BEC23 /* User.swift in Sources */,
34EE0C562935F944002BEC23 /* BrowseQuest+Stub.swift in Sources */,
34EE0C642935FD6B002BEC23 /* BrowseViewModelTests.swift in Sources */,
3416FC8E292B593C00B504C5 /* Quest+Stub.swift in Sources */,
340FDFD5292B5DB700C4E3DC /* DefaultQuestUseCase.swift in Sources */,
3416FC93292B59D300B504C5 /* QuestRepositoryMock.swift in Sources */,
34EE0C652935FD79002BEC23 /* BrowseViewModel.swift in Sources */,
340FDFDE292B7A2C00C4E3DC /* QuestUseCaseMock.swift in Sources */,
34EE0C542935F8F7002BEC23 /* BrowseQuest.swift in Sources */,
34EE0C5D2935FA6E002BEC23 /* BrowseRepository.swift in Sources */,
340FDFDB292B7A1500C4E3DC /* QuestViewModelTests.swift in Sources */,
34EE0C622935FD0C002BEC23 /* BrowseUseCaseMock.swift in Sources */,
34FF6C60292B8BC9002AFD4D /* QuestViewModel.swift in Sources */,
34EE0C5F2935FBA1002BEC23 /* BrowseUseCaseTests.swift in Sources */,
340FDFD4292B5DA100C4E3DC /* QuestUseCase.swift in Sources */,
34EE0C5C2935FA4C002BEC23 /* BrowseUseCase.swift in Sources */,
340FDFD3292B5CE300C4E3DC /* QuestsRepository.swift in Sources */,
34EE0C5B2935FA2E002BEC23 /* BrowseRepositoryMock.swift in Sources */,
34EE0C602935FC47002BEC23 /* DefaultBrowseUseCase.swift in Sources */,
340A72472934573F00B26AA6 /* AuthRepository.swift in Sources */,
34EE0C592935F98D002BEC23 /* User+Stub.swift in Sources */,
34EE0C662935FD7D002BEC23 /* BrowseItemViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import UIKit
final class BrowseSceneDIContainer {

// MARK: - Repositories
func makeBrowseRepository() -> BrowseRepository {
return BrowseMockRepo()
}

// MARK: - Use Cases
func makeBrowseUseCase() -> BrowseUseCase {
return DefaultBrowseUseCase(browseRepository: makeBrowseRepository())
}

// MARK: - View Models
func makeBrowseViewModel() -> BrowseViewModel {
return BrowseViewModel()
return BrowseViewModel(browseUseCase: makeBrowseUseCase())
}

// MARK: - View Controller
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// DefaultBrowseUseCase.swift
// DailyQuest
//
// Created by jinwoong Kim on 2022/11/29.
//

import Foundation

import RxSwift

final class DefaultBrowseUseCase {
private let browseRepository: BrowseRepository

init(browseRepository: BrowseRepository) {
self.browseRepository = browseRepository
}
}

extension DefaultBrowseUseCase: BrowseUseCase {
func excute() -> Observable<[BrowseQuest]> {
return browseRepository.fetch()
}
}

final class BrowseMockRepo: BrowseRepository {
func fetch() -> RxSwift.Observable<[BrowseQuest]> {
return .just([BrowseQuest(user: User(uuid: "", nickName: "test", profileURL: "", backgroundImageURL: "", description: "", allow: false), quests: [])])
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// BrowseUseCase.swift
// DailyQuest
//
// Created by jinwoong Kim on 2022/11/29.
//

import Foundation

import RxSwift

protocol BrowseUseCase {
func excute() -> Observable<[BrowseQuest]>
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class BrowseViewController: UITableViewController {
super.viewDidLoad()

configure()

bind()
}

Expand All @@ -42,18 +43,15 @@ final class BrowseViewController: UITableViewController {
}

private func bind() {
viewModel
let output = viewModel.transform(input: BrowseViewModel.Input(viewDidLoad: .just(()).asObservable()))

output
.data
.bind(to: tableView.rx.items(cellIdentifier: BrowseCell.reuseIdentifier, cellType: BrowseCell.self)) { row, item, cell in
cell.setup(with: BrowseItemViewModel(user: item.0, quests: item.1))
.drive(tableView.rx.items(cellIdentifier: BrowseCell.reuseIdentifier, cellType: BrowseCell.self)) { row, item, cell in
cell.setup(with: item)
}
.disposed(by: disposableBag)

tableView.rx.itemSelected
.subscribe(onNext: { indexPath in
print(self.viewModel.users[indexPath.row])
})
.disposed(by: disposableBag)

}
}

Expand All @@ -65,14 +63,4 @@ extension BrowseViewController {
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return (75.0 * CGFloat(viewModel.cellCount[indexPath.row])) + 20 + 75
}

/**
viewModel에서 총 몇개의 BrowseCell을 만들어야하는지 결정합니다.
viewModel에는 UseCase를 통해 들어온 (User, [Quest]) 데이터에서 퀘스트의 **길이** 정보를 담는 프로퍼티(정ㅅ배열)가 있어야 합니다.
Note. 여기에서는 Quest 정보 자체가 필요하진 않습니다. 해당 배열의 아이템들은 위에서 사용할, BrowseCell의 크기를 결정하고,
배열 자체의 길이는 이 메서드의 결과를 결정합니다.
*/
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.cellCount.count
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,42 @@
import Foundation

import RxSwift
import RxCocoa

final class BrowseViewModel {
let user1 = User(uuid: "", nickName: "jinwoong", profileURL: "", backgroundImageURL: "", description: "", allow: false)
let quests1 = [
Quest(groupId: UUID(), uuid: UUID(), date: Date(), title: "물마시기", currentCount: 2, totalCount: 5),
Quest(groupId: UUID(), uuid: UUID(), date: Date(), title: "코딩하기", currentCount: 0, totalCount: 10)
]

let data: Observable<[(User, [Quest])]>
private(set) var users: [User] = []

let cellCount = [2]

init() {
self.data = .just([(user1, quests1)])
self.users.append(contentsOf: [user1])
private let browseUseCase: BrowseUseCase
private(set) var cellCount: [Int] = []

init(browseUseCase: BrowseUseCase) {
self.browseUseCase = browseUseCase
}

struct Input {
let viewDidLoad: Observable<Void>
}

struct Output {
let data: Driver<[BrowseItemViewModel]>
}

func transform(input: Input) -> Output {
let data = input
.viewDidLoad
.flatMap { _ in
self.browseUseCase.excute()
}
.map(transform(with:))
.do(onNext: { [weak self] items in
self?.cellCount = items.map({ $0.quests.count })
})
.asDriver(onErrorJustReturn: [])

return Output(data: data)
}

private func transform(with browseQuests: [BrowseQuest]) -> [BrowseItemViewModel] {
return browseQuests.map { browseQuest in
BrowseItemViewModel(user: browseQuest.user, quests: browseQuest.quests)
}
}
}

/**
Usecase
- fetching quests, it contains user and his quests.
*/
Loading

0 comments on commit 5d38779

Please sign in to comment.