Skip to content

Commit fd502aa

Browse files
authored
[NL-55] : Onboarding 기능 수정 (#28)
* [NL-55] : SplashViewContoller + ViewModel 리팩토링 * [NL-55] : OnboardingViewController + viewModel Refactor - Routing시 delegate 설정 * [NL-55] : setFactories 호출 변경 - viewModel let으로 변경
1 parent 450bde0 commit fd502aa

File tree

8 files changed

+224
-202
lines changed

8 files changed

+224
-202
lines changed

Common/Lib/Sources/Router/AppRouter.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public enum AppRoute: Hashable {
4545
@MainActor
4646
public protocol Routable: AnyObject {
4747
func navigate(to route: Any, how: NavigateType, with data: [String: Any])
48+
func setFactories()
4849
}
4950

5051
public final class AppRouter: Routable {
@@ -62,7 +63,7 @@ public final class AppRouter: Routable {
6263
guard let appRoute = route as? AppRoute else { return }
6364
guard let factory = factories[appRoute] else { return }
6465
let subRouter = factory()
65-
66+
6667
switch appRoute {
6768
case .fortune:
6869
break
@@ -72,11 +73,14 @@ public final class AppRouter: Routable {
7273
break
7374
case .onboarding(let onboardingRoute):
7475
guard let onboardingRoute = onboardingRoute else { return }
76+
7577
subRouter.navigate(to: onboardingRoute, how: how, with: data)
7678
case .setting:
7779
break
7880
}
7981
}
82+
83+
public func setFactories() { }
8084
}
8185

8286
extension Routable {

Common/Lib/Sources/Router/OnbaordingRoute.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
//
77

88
import Foundation
9+
import UIKit
910

1011
public enum OnboardingRoute {
1112
case splash
1213
case onboarding
13-
case agreement
14-
case timePicker
14+
case agreement
15+
case timePicker
1516
}

Feature/Onboarding/Sources/OnbaordingRouter.swift

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,38 @@ public final class OnboardingRouter: Routable {
1313
private var factories: [OnboardingRoute: () -> UIViewController]
1414

1515
public init() {
16-
self.factories = [
17-
.splash: { SplashViewcontroller() },
18-
.agreement: { AgreementViewController() },
19-
.onboarding: { OnboardingViewController() },
20-
.timePicker: { TimePickerBottomSheetViewController() },
21-
]
16+
self.factories = [:]
17+
self.setFactories()
2218
}
19+
20+
public func setFactories() {
21+
self.factories = [
22+
.splash: {
23+
let viewModel = SplashViewModel()
24+
return SplashViewcontroller(viewModel: viewModel, router: self)
25+
},
26+
.agreement: { AgreementViewController() },
27+
.onboarding: { OnboardingViewController(router: self) },
28+
.timePicker: { TimePickerBottomSheetViewController() },
29+
]
30+
}
2331

2432
public func navigate(to route: Any, how: NavigateType, with data: [String: Any]) {
2533
guard let onboardingRoute = route as? OnboardingRoute else { return }
2634
guard let factory = factories[onboardingRoute] else { return }
2735
let viewController = factory()
28-
36+
37+
if onboardingRoute == .agreement {
38+
if let agreementVC = viewController as? AgreementViewController,
39+
let delegate = data["delegate"] as? AgreementViewDelegate {
40+
agreementVC.delegate = delegate
41+
}
42+
} else if onboardingRoute == .timePicker {
43+
if let timePickerVC = viewController as? TimePickerBottomSheetViewController,
44+
let delegate = data["delegate"] as? TimePickerBottomSheetDelegate {
45+
timePickerVC.delegate = delegate
46+
}
47+
}
2948
manageViewController(viewController, how: how)
3049
}
3150
}

Feature/Onboarding/Sources/Onboarding/OnboardingViewModel.swift

Lines changed: 59 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,94 +7,76 @@
77

88
import Combine
99
import Foundation
10-
11-
public enum OnboardingAction {
12-
case checkNameFormat(name: String)
13-
case genderSelected(isSelected: GenderType)
14-
case checkBirthFormat(birth: String)
15-
case bornTimeSelected(bornTime: BornType)
16-
case nextButtonTap
17-
case completeButtonTap
18-
}
19-
20-
public protocol OnboardingOutputProtocol {
21-
var showNameError: AnyPublisher<Bool, Never> { get }
22-
var showBirthError: AnyPublisher<Bool, Never> { get }
23-
var isNextButtonEnabled: AnyPublisher<Bool, Never> { get }
24-
}
25-
26-
public protocol OnboardingViewModelProtocol: OnboardingOutputProtocol {
27-
var inputStream: PassthroughSubject<OnboardingAction, Never> { get }
28-
}
29-
30-
public class OnboardingViewModel: OnboardingViewModelProtocol {
31-
var stor: Set<AnyCancellable> = []
32-
33-
@Published private var _isNameValid: Bool = false
34-
@Published private var _isBirthDateValid: Bool = false
35-
@Published private var _isBornTimeValied: Bool = false
36-
37-
public var inputStream: PassthroughSubject<OnboardingAction, Never> = .init()
38-
39-
public var isNextButtonEnabled: AnyPublisher<Bool, Never> {
40-
Publishers.CombineLatest3($_isNameValid, $_isBirthDateValid, $_isBornTimeValied).map {
41-
(nameValid, birthBalid, bornTimeValid) in
42-
return nameValid && birthBalid && bornTimeValid
10+
import Lib
11+
12+
public class OnboardingViewModel {
13+
14+
enum Input {
15+
case checkNameFormat(name: String)
16+
case genderSelected(isSelected: GenderType)
17+
case checkBirthFormat(birth: String)
18+
case bornTimeSelected(bornTime: BornType)
19+
case nextButtonTap
20+
case completeButtonTap
21+
case timePickerTap
4322
}
44-
.eraseToAnyPublisher()
45-
}
46-
47-
public var showNameError: AnyPublisher<Bool, Never> {
48-
$_isNameValid
49-
.eraseToAnyPublisher()
50-
}
51-
52-
public var showBirthError: AnyPublisher<Bool, Never> {
53-
$_isBirthDateValid
54-
.eraseToAnyPublisher()
55-
}
56-
57-
private var state: State = .init()
58-
59-
public init() {
60-
inputStream
61-
.sink { [weak self] action in
62-
guard let self = self else { return }
63-
switch action {
64-
case .checkNameFormat(let name):
65-
self._isNameValid = checkNameFormat(name: name)
66-
if self._isNameValid { self.state.name = name }
67-
case .genderSelected(let isSelected):
68-
self.state.gender = isSelected
69-
case .checkBirthFormat(let birth):
70-
self._isBirthDateValid = checkBirthFormat(birth: birth)
71-
if self._isBirthDateValid { self.state.birthDate = birth }
72-
case .bornTimeSelected(let bornTime):
73-
switch bornTime {
74-
case .dontKnow(let isSelected):
75-
self._isBornTimeValied = (self.state.bornTime != nil || !isSelected)
76-
case .time(let time):
77-
self._isBornTimeValied = true
78-
self.state.bornTime = bornTime
79-
}
23+
24+
struct Output {
25+
let showNameError : PassthroughSubject<Bool, Never> = .init()
26+
let showBirthError : PassthroughSubject<Bool, Never> = .init()
27+
let isNextButtonEnabled: PassthroughSubject<Bool, Never> = .init()
28+
let navigate : PassthroughSubject<OnboardingRoute, Never> = .init()
29+
}
30+
31+
let output : Output = Output()
32+
33+
private var _isNameValid: Bool = false
34+
private var _isBirthDateValid: Bool = false
35+
private var _isBornTimeValied: Bool = false
36+
37+
private var state: State = .init()
38+
39+
func send(input : Input) {
40+
switch input {
41+
case .checkNameFormat(name: let name):
42+
self._isNameValid = checkNameFormat(name: name)
43+
if self._isNameValid { self.state.name = name }
44+
self.output.showNameError.send(self._isNameValid)
45+
self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied)
46+
case .genderSelected(isSelected: let isSelected):
47+
self.state.gender = isSelected
48+
case .checkBirthFormat(birth: let birth):
49+
self._isBirthDateValid = checkBirthFormat(birth: birth)
50+
if self._isBirthDateValid { self.state.birthDate = birth }
51+
self.output.showBirthError.send(self._isBirthDateValid)
52+
self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied)
53+
case .bornTimeSelected(bornTime: let bornTime):
54+
switch bornTime {
55+
case .dontKnow(let isSelected):
56+
self._isBornTimeValied = (self.state.bornTime != nil || !isSelected)
57+
case .time(let time):
58+
self._isBornTimeValied = true
59+
self.state.bornTime = time
60+
}
61+
self.output.isNextButtonEnabled.send(_isNameValid && _isBirthDateValid && _isBornTimeValied)
8062
case .nextButtonTap:
81-
// TODO: Modal present
82-
break
63+
self.output.navigate.send(.agreement)
8364
case .completeButtonTap:
84-
// TODO: API 연결 부분
85-
break
65+
break
66+
case .timePickerTap :
67+
self.output.navigate.send(.timePicker)
8668
}
87-
}
88-
.store(in: &stor)
89-
}
69+
}
70+
71+
public init() { }
9072
}
9173

9274
extension OnboardingViewModel {
9375
struct State {
9476
var name: String?
9577
var gender: GenderType?
9678
var birthDate: String?
97-
var bornTime: BornType?
79+
var bornTime: String?
9880
}
9981
}
10082

0 commit comments

Comments
 (0)