Skip to content

Commit

Permalink
Merge pull request #25 from boostcampwm-2022/feature/QuestView
Browse files Browse the repository at this point in the history
QuestView 작성, 버튼 클릭시, AddQuestsView present
  • Loading branch information
jinwoong16 committed Nov 17, 2022
2 parents c302b7e + 15119f1 commit 9941094
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 4 deletions.
25 changes: 23 additions & 2 deletions DailyQuest/DailyQuest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
3449AD5B2922164B00B87619 /* Quest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449AD5A2922164B00B87619 /* Quest.swift */; };
3449AD5D2922197000B87619 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449AD5C2922197000B87619 /* User.swift */; };
3449AD6029222B3900B87619 /* UserInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3449AD5F29222B3900B87619 /* UserInfoCell.swift */; };
34874AA0292509A4000570DF /* QuestViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34874A9F292509A4000570DF /* QuestViewHeader.swift */; };
34874AA229250C43000570DF /* UIButton+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34874AA129250C43000570DF /* UIButton+.swift */; };
34874AA629252088000570DF /* AddQuestsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34874AA529252088000570DF /* AddQuestsViewController.swift */; };
349955122923220E007AB99E /* SwiftUIPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349955112923220E007AB99E /* SwiftUIPreview.swift */; };
3499551529232533007AB99E /* UIColor+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3499551429232533007AB99E /* UIColor+.swift */; };
3499551E29233DEF007AB99E /* QuestCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3499551D29233DEF007AB99E /* QuestCell.swift */; };
Expand Down Expand Up @@ -45,6 +48,8 @@
34ACC364291DEF6100741371 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 34ACC363291DEF6100741371 /* FirebaseFirestore */; };
34ACC366291DEF6100741371 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = 34ACC365291DEF6100741371 /* FirebaseStorage */; };
34ACC36C291DF0DD00741371 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 34ACC36B291DF0DD00741371 /* GoogleService-Info.plist */; };
34EE6EB72924C674005AF583 /* QuestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE6EB62924C674005AF583 /* QuestView.swift */; };
34EE6EB92924CAA1005AF583 /* QuestViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EE6EB82924CAA1005AF583 /* QuestViewModel.swift */; };
A51189C329226E66008A9D33 /* UserQuestEntity+Mapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51189C229226E66008A9D33 /* UserQuestEntity+Mapping.swift */; };
A51F01C82923392F0031ECA2 /* UserInfoStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51F01C72923392F0031ECA2 /* UserInfoStorage.swift */; };
A51F01CA2923397E0031ECA2 /* UserInfoEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51F01C92923397E0031ECA2 /* UserInfoEntity.swift */; };
Expand Down Expand Up @@ -85,6 +90,9 @@
3449AD5A2922164B00B87619 /* Quest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Quest.swift; sourceTree = "<group>"; };
3449AD5C2922197000B87619 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
3449AD5F29222B3900B87619 /* UserInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoCell.swift; sourceTree = "<group>"; };
34874A9F292509A4000570DF /* QuestViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestViewHeader.swift; sourceTree = "<group>"; };
34874AA129250C43000570DF /* UIButton+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+.swift"; sourceTree = "<group>"; };
34874AA529252088000570DF /* AddQuestsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddQuestsViewController.swift; sourceTree = "<group>"; };
349955112923220E007AB99E /* SwiftUIPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIPreview.swift; sourceTree = "<group>"; };
3499551429232533007AB99E /* UIColor+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+.swift"; sourceTree = "<group>"; };
3499551D29233DEF007AB99E /* QuestCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestCell.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -117,6 +125,8 @@
34ACC34D291DE9C100741371 /* DailyQuestUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyQuestUITests.swift; sourceTree = "<group>"; };
34ACC34F291DE9C100741371 /* DailyQuestUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyQuestUITestsLaunchTests.swift; sourceTree = "<group>"; };
34ACC36B291DF0DD00741371 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; 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>"; };
A51189C229226E66008A9D33 /* UserQuestEntity+Mapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserQuestEntity+Mapping.swift"; sourceTree = "<group>"; };
A51F01C72923392F0031ECA2 /* UserInfoStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoStorage.swift; sourceTree = "<group>"; };
A51F01C92923397E0031ECA2 /* UserInfoEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoEntity.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -192,6 +202,7 @@
children = (
349955112923220E007AB99E /* SwiftUIPreview.swift */,
3499551429232533007AB99E /* UIColor+.swift */,
34874AA129250C43000570DF /* UIButton+.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -232,6 +243,7 @@
34995519292332A9007AB99E /* Home */ = {
isa = PBXGroup;
children = (
34EE6EB52924C657005AF583 /* View */,
34A529DE29247F13001BAD34 /* ViewModel */,
34A529DD29247F0C001BAD34 /* ViewController */,
34A529D629247A52001BAD34 /* Flow */,
Expand Down Expand Up @@ -306,13 +318,15 @@
isa = PBXGroup;
children = (
34A529DF29247F1F001BAD34 /* HomeViewController.swift */,
34874AA529252088000570DF /* AddQuestsViewController.swift */,
);
path = ViewController;
sourceTree = "<group>";
};
34A529DE29247F13001BAD34 /* ViewModel */ = {
isa = PBXGroup;
children = (
34EE6EB82924CAA1005AF583 /* QuestViewModel.swift */,
);
path = ViewModel;
sourceTree = "<group>";
Expand Down Expand Up @@ -421,10 +435,12 @@
path = Data;
sourceTree = "<group>";
};
34EE6EB12924B3CF005AF583 /* View */ = {
34EE6EB52924C657005AF583 /* View */ = {
isa = PBXGroup;
children = (
34A529EA2924B077001BAD34 /* UserInfoView.swift */,
34EE6EB62924C674005AF583 /* QuestView.swift */,
34874A9F292509A4000570DF /* QuestViewHeader.swift */,
34A529EA2924B077001BAD34 /* UserInfoView.swift */,
);
path = View;
sourceTree = "<group>";
Expand Down Expand Up @@ -707,8 +723,10 @@
3499552329234D5F007AB99E /* BrowseCell.swift in Sources */,
3499551E29233DEF007AB99E /* QuestCell.swift in Sources */,
34A529DC29247BB6001BAD34 /* HomeSceneDIContainer.swift in Sources */,
34874AA229250C43000570DF /* UIButton+.swift in Sources */,
34A529E7292481E1001BAD34 /* BrowseCoordinator.swift in Sources */,
34A529D329247903001BAD34 /* TabCoordinator.swift in Sources */,
34EE6EB92924CAA1005AF583 /* QuestViewModel.swift in Sources */,
3449AD5D2922197000B87619 /* User.swift in Sources */,
A51F01CD29233ABB0031ECA2 /* RealmUserInfoStorage.swift in Sources */,
A51F01DA292345990031ECA2 /* BrowseQuest.swift in Sources */,
Expand All @@ -720,14 +738,17 @@
34A529D529247932001BAD34 /* AppCoordinator.swift in Sources */,
B50078D629222F3F0070AFC4 /* CircleCheckView.swift in Sources */,
3499552729235D1E007AB99E /* BrowseItemViewModel.swift in Sources */,
34874AA629252088000570DF /* AddQuestsViewController.swift in Sources */,
349955292923600A007AB99E /* BrowseViewController.swift in Sources */,
34EE6EB72924C674005AF583 /* QuestView.swift in Sources */,
B58DFC0A29227DA800C68A4B /* CalendarCell.swift in Sources */,
3499551529232533007AB99E /* UIColor+.swift in Sources */,
34A529DA29247B9C001BAD34 /* AppDIContainer.swift in Sources */,
34ACC32D291DE9C000741371 /* AppDelegate.swift in Sources */,
A5AC96D929223648003B7637 /* RealmStorage.swift in Sources */,
A51189C329226E66008A9D33 /* UserQuestEntity+Mapping.swift in Sources */,
A51F01D3292340360031ECA2 /* BrowseQuestsStorage.swift in Sources */,
34874AA0292509A4000570DF /* QuestViewHeader.swift in Sources */,
34A529EB2924B077001BAD34 /* UserInfoView.swift in Sources */,
A51F01CA2923397E0031ECA2 /* UserInfoEntity.swift in Sources */,
A51F01D8292343A80031ECA2 /* RealmBrowseQuestsStorage.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@

import UIKit

import RxSwift

protocol HomeCoordinator: Coordinator {
func showProfileFlow()
func showAddQuestFlow()
func showAddFriendsFlow()
}

final class DefaultHomeCoordinator: HomeCoordinator {
private var disposableBag = DisposeBag()

var finishDelegate: CoordinatorFinishDelegate?
var childCoordinators: [Coordinator] = []
var navigationController: UINavigationController
Expand All @@ -28,14 +32,25 @@ final class DefaultHomeCoordinator: HomeCoordinator {
func start() {
let homeViewController = homeSceneDIContainer.makeHomeViewController()
navigationController.pushViewController(homeViewController, animated: false)

homeViewController
.coordinatorPublisher
.bind(onNext: { [weak self] event in
switch event {
case .showAddQuestsFlow:
self?.showAddQuestFlow()
}
})
.disposed(by: disposableBag)
}

func showProfileFlow() {

}

func showAddQuestFlow() {

let addQuestsViewController = AddQuestsViewController()
navigationController.present(addQuestsViewController, animated: true)
}

func showAddFriendsFlow() {
Expand Down
69 changes: 69 additions & 0 deletions DailyQuest/DailyQuest/Presentation/Home/View/QuestView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// QuestView.swift
// DailyQuest
//
// Created by jinwoong Kim on 2022/11/16.
//

import UIKit

import RxSwift
import RxCocoa

final class QuestView: UITableView {
private var viewModel: QuestViewModel!
private var disposableBag = DisposeBag()

override init(frame: CGRect, style: UITableView.Style) {
super.init(frame: frame, style: style)

rowHeight = 75

register(QuestCell.self, forCellReuseIdentifier: QuestCell.reuseIdentifier)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func setup(with viewModel: QuestViewModel) {
self.viewModel = viewModel

bind()
}

private func bind() {
viewModel
.data
.bind(to: rx.items(cellIdentifier: QuestCell.reuseIdentifier, cellType: QuestCell.self)) { row, item, cell in
cell.setup(with: item)
cell.backgroundColor = .white
}
.disposed(by: disposableBag)
}
}

/**
`QuestView`의 델리게이트 역할을 수행할 클래스입니다.
생성자를 통해 header 정보를 받는 이유는, `func tableView(_:viewForHeaderInSection)`메서드에서 헤더를 지정해주기 때문입니다.
*/
final class QuestViewDelegate: NSObject, UITableViewDelegate {
private let header: QuestViewHeader

init(header: QuestViewHeader) {
self.header = header
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 75
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return header
}

deinit {
print("deinit")
}
}

65 changes: 65 additions & 0 deletions DailyQuest/DailyQuest/Presentation/Home/View/QuestViewHeader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// QuestViewHeader.swift
// DailyQuest
//
// Created by jinwoong Kim on 2022/11/16.
//

import UIKit

import RxSwift
import RxCocoa
import SnapKit

final class QuestViewHeader: UIStackView {
private var disposableBag = DisposeBag()
var buttonDidClick = PublishSubject<Void>()

// MARK: - Components
private lazy var titleLabel: UILabel = {
let titleLabel = UILabel()
titleLabel.text = "Today Quest"
titleLabel.textColor = .maxViolet
titleLabel.font = UIFont.boldSystemFont(ofSize: 32)

return titleLabel
}()

private lazy var plusButton: UIButton = {
var config = UIButton.Configuration.maxStyle()
let plusButton = UIButton(configuration: config)

return plusButton
}()

// MARK: - Methods
convenience init() {
self.init(frame: .zero)

axis = .horizontal
alignment = .center
distribution = .equalSpacing
isLayoutMarginsRelativeArrangement = true
layoutMargins = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)

configureUI()
bind()
}

private func configureUI() {
addArrangedSubview(titleLabel)
addArrangedSubview(plusButton)
}

/**
버튼이 클릭되면 `buttonDidClick` subject가 이벤트를 방출합니다.
눌려졌다는 정보만 있으면 되므로, output type은 Void입니다.
*/
private func bind() {
plusButton.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.buttonDidClick.onNext(())
})
.disposed(by: disposableBag)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// AddQuestsViewController.swift
// DailyQuest
//
// Created by jinwoong Kim on 2022/11/16.
//

import UIKit

import SnapKit

final class AddQuestsViewController: UIViewController {

private lazy var indicateMessage: UILabel = {
let indicateMessage = UILabel()
indicateMessage.text = "여기서 새로운 퀘스트를 추가합니다."

return indicateMessage
}()

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .systemGray

configureUI()
}

private func configureUI() {
view.addSubview(indicateMessage)

indicateMessage.snp.makeConstraints { make in
make.center.equalToSuperview()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,30 @@

import UIKit

import RxSwift
import RxCocoa
import SnapKit

final class HomeViewController: UIViewController {
enum Event {
case showAddQuestsFlow
}

var coordinatorPublisher = PublishSubject<Event>()

private var disposableBag = DisposeBag()
private var questViewDelegate: QuestViewDelegate?

private lazy var questView: QuestView = {
let questView = QuestView()
questView.setup(with: QuestViewModel())

return questView
}()

private lazy var questViewHeader: QuestViewHeader = {
return QuestViewHeader()
}()

// MARK: - Life Cycle
// static func create(with viewModel: HomeViewModel)
Expand All @@ -18,6 +40,33 @@ final class HomeViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
questViewDelegate = QuestViewDelegate(header: questViewHeader)

view.backgroundColor = .white

view.addSubview(questView)

questView.delegate = questViewDelegate
questView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}

bind()
}

private func bind() {
/**
Header에서 버튼이 눌려졌는지를 수신하고 있습니다.
버튼이 눌러지면 bind내의 클로저가 실행되고, 이는 다시 coordinatorPublisher가 이벤트를 방출하게 합니다.
이 버튼이 눌러졌을 때에는 퀘스트를 추가하는 화면이 띄워져야 하므로, 이벤트의 종류는 .`showAddQuestsFlow`입니다.
Note. Combine에서는 `assign(to:)` 오퍼레이터 메서드를 사용하면 이 위치에서 cancellable을 반환하지 않고(rx에서는 disposable)
이벤트를 연계해줄 수 있지만, rx에서는 동일한 역할을 해주는 오퍼레이터가 없어서 disposableBag에 `Disposable`을 담아주는 것에 유념해주세요.
*/
questViewHeader
.buttonDidClick
.bind(onNext: { [weak self] _ in
self?.coordinatorPublisher.onNext(.showAddQuestsFlow)
})
.disposed(by: disposableBag)
}
}
Loading

0 comments on commit 9941094

Please sign in to comment.