Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Design] 사용자 등록 뷰 디자인 #60

Merged
merged 16 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)

let initialViewController: UIViewController
if let houseName = UserDefaults.standard.object(forKey: Constant.houseNameUserDefaultKey) as? String {
let viewModel = HomeViewModel(houseName: houseName)
initialViewController = HomeViewController(viewModel: viewModel)
} else {
initialViewController = RegisterViewController()
initialViewController = RegisterViewController(viewModel: RegisterViewModel())
}

let navigationController = UINavigationController(rootViewController: initialViewController)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Combine

protocol ViewModelType {
associatedtype Input
associatedtype Output

func transform(input: AnyPublisher<Input, Never>) -> AnyPublisher<Output, Never>
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import UIKit
import MHFoundation
import Combine

public final class RegisterViewController: UIViewController {
// MARK: - Property
private var viewModel = RegisterViewModel()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p3
private let 으로는 못 쓰나용 ??

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: 생성자에서 viewmodel을 받고있는데 프로퍼티가 뷰모델 객체를 들고있는게 어색하게 느껴집니다..

Suggested change
private var viewModel = RegisterViewModel()
private let viewModel: RegisterViewModel

이게 더 낫지 않을까요??

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

옹 인정합니다

private let input = PassthroughSubject<RegisterViewModel.Input, Never>()
private var cancellables = Set<AnyCancellable>()

// MARK: - UI Components
private let coverImageView: UIImageView = {
let backgroundImageView = UIImageView()
backgroundImageView.image = UIImage.pinkBook

return backgroundImageView
}()
private let registerTextLabel: UILabel = {
let registerFont = UIFont.ownglyphBerry(size: 24)

let textLabel = UILabel()
textLabel.text = """
추억을 간직할
기록소 이름을 작성해주세요
"""
textLabel.textAlignment = .center
textLabel.font = registerFont
textLabel.numberOfLines = 2

return textLabel
}()
private let registerTextField: UITextField = {
let registerFont = UIFont.ownglyphBerry(size: 12)

let textField = UITextField()
textField.font = registerFont

var attributedText = AttributedString(stringLiteral: "기록소")
attributedText.font = registerFont
textField.attributedPlaceholder = NSAttributedString(attributedText)

return textField
}()
private let registerButton: UIButton = {
let registerButton = UIButton(type: .custom)

var attributedString = AttributedString(stringLiteral: "다음")
attributedString.font = UIFont.ownglyphBerry(size: 16)
attributedString.foregroundColor = UIColor.black
registerButton.setAttributedTitle(NSAttributedString(attributedString), for: .normal)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
registerButton.setAttributedTitle(NSAttributedString(attributedString), for: .normal)
registerButton.setAttributedTitle(NSAttributedString(attributedString), for: .normal)
registerButton.setAttributedTitle(<#T##title: NSAttributedString?##NSAttributedString?#>, for: .disabled)

버튼의 그림자를 주는 것보단 이런식으로 disabled일 때 글자 색을 회색? 정도로 해주면 더.. 이쁠 것 같숩니당...ㅎㅅㅎ (해당 부분 디자인을 안만들어놔서 죄송함돠..)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎㅎ 수정 완! 글자가 작은 거 같아서 그것도 좀 키웠습니다.


var disabledAttributedString = AttributedString(stringLiteral: "다음")
disabledAttributedString.font = UIFont.ownglyphBerry(size: 16)
disabledAttributedString.foregroundColor = UIColor.gray
registerButton.setAttributedTitle(NSAttributedString(disabledAttributedString), for: .disabled)

registerButton.backgroundColor = .mhSection
registerButton.layer.borderColor = UIColor.mhBorder.cgColor
registerButton.layer.borderWidth = 1
registerButton.layer.cornerRadius = 12

return registerButton
}()

// MARK: - Initializer
public init(viewModel: RegisterViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
self.viewModel = RegisterViewModel()
super.init(coder: coder)
}

// MARK: - Lifecycle
public override func viewDidLoad() {
super.viewDidLoad()

setup()
bind()
configureAddSubview()
configureConstraints()
Comment on lines +80 to +83
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: 꼭 그래야하는 건 아닌데 가독성 측면에서 아래 메서드 순서와 함수 호출 순서를 맞추면 좋을 것 같아요 !

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

순서 맞추는 게 좋을 것 같네요!

}

private func setup() {
view.backgroundColor = .baseBackground

addTouchEventToRegisterButton(registerButton)
addEditingChangedEventToRegisterTextField(registerTextField)
coverImageView.isUserInteractionEnabled = true
registerButton.isEnabled = false
}

private func bind() {
let output = viewModel.transform(input: input.eraseToAnyPublisher())

output.sink { [weak self] event in
switch event {
case .registerButtonEnabled(let isEnabled):
self?.registerButton.isEnabled = isEnabled
case .moveToHome(let houseName):
let homeViewController = HomeViewController(viewModel: HomeViewModel(houseName: houseName))
self?.navigationController?.pushViewController(homeViewController, animated: false)
self?.navigationController?.viewControllers.removeFirst()
}
}.store(in: &cancellables)
}

private func configureAddSubview() {
view.addSubview(coverImageView)
view.addSubview(registerTextLabel)
view.addSubview(registerTextField)
view.addSubview(registerButton)
}

private func configureConstraints() {
coverImageView.setCenter(view: view)
coverImageView.setWidth(view.frame.width - 50)
coverImageView.setHeight(240)

registerTextLabel.setAnchor(
top: coverImageView.topAnchor,
leading: coverImageView.leadingAnchor, constantLeading: 80,
trailing: coverImageView.trailingAnchor, constantTrailing: 40,
height: 96
)

let registerTextFieldBackground = registerTextField.embededInDefaultBackground(
with: UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 5)
)
coverImageView.addSubview(registerTextFieldBackground)
registerTextFieldBackground.setAnchor(
top: registerTextLabel.bottomAnchor,
leading: coverImageView.leadingAnchor, constantLeading: 80,
trailing: coverImageView.trailingAnchor, constantTrailing: 40,
height: 44
)

let registerButtonBackground = UIView()
registerButtonBackground.backgroundColor = .mhSection
registerButtonBackground.layer.cornerRadius = 12 + 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: 12 + 1은 무슨뜻인가요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registerbutton의 cornerradius가 12이고 registerbuttonbackground의 cornerradius가 12 + 1입니다.

registerButtonBackground.clipsToBounds = true
registerButtonBackground.addSubview(registerButton)
registerButton.setAnchor(
top: registerButtonBackground.topAnchor, constantTop: 3,
leading: registerButtonBackground.leadingAnchor, constantLeading: 4,
bottom: registerButtonBackground.bottomAnchor, constantBottom: 3,
trailing: registerButtonBackground.trailingAnchor, constantTrailing: 4
)

coverImageView.addSubview(registerButtonBackground)
registerButtonBackground.setAnchor(
top: registerTextFieldBackground.bottomAnchor, constantTop: 10,
leading: view.leadingAnchor, constantLeading: 260,
width: 60,
height: 36
)
}

private func addTouchEventToRegisterButton(_ button: UIButton) {
let uiAction = UIAction { [weak self] _ in
guard let self, let text = self.registerTextField.text else { return }
self.input.send(.registerButtonTapped(text: text))
}
registerButton.addAction(uiAction, for: .touchUpInside)
}

private func addEditingChangedEventToRegisterTextField(_ textfield: UITextField) {
let uiAction = UIAction { [weak self] _ in
guard let self else { return }
self.input.send(.registerTextFieldEdited(text: textfield.text))
}
registerTextField.addAction(uiAction, for: .editingChanged)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import MHFoundation
import Combine

public final class RegisterViewModel: ViewModelType {
enum Input {
case registerTextFieldEdited(text: String?)
case registerButtonTapped(text: String)
}

enum Output {
case registerButtonEnabled(isEnabled: Bool)
case moveToHome(destination: String)
}

private let output = PassthroughSubject<Output, Never>()
private var cancellables = Set<AnyCancellable>()

public init() { }

func transform(input: AnyPublisher<Input, Never>) -> AnyPublisher<Output, Never> {
input.sink { [weak self] event in
switch event {
case .registerTextFieldEdited(let text):
self?.validateTextField(text: text)
case .registerButtonTapped(let text):
self?.registerButtonTapped(text: text)
}
}.store(in: &cancellables)

return output.eraseToAnyPublisher()
}

private func validateTextField(text: String?) {
guard let text else {
output.send(.registerButtonEnabled(isEnabled: false))
return
}
output.send(.registerButtonEnabled(isEnabled: !text.isEmpty && text.count < 11))
}

private func registerButtonTapped(text: String) {
UserDefaults.standard.set(
text,
forKey: Constant.houseNameUserDefaultKey
)
output.send(.moveToHome(destination: text))
}
}
Loading