Skip to content

Commit

Permalink
♻️ Refactor: 유효성 검증 로직 VIP 사이클로 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
anyukyung committed Nov 15, 2023
1 parent 4bd5c52 commit c534805
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 42 deletions.
18 changes: 17 additions & 1 deletion iOS/Layover/Layover.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
194552132B03AFFC00299768 /* DummyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194552122B03AFFC00299768 /* DummyViewController.swift */; };
19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFCD2B02410F003B35F2 /* AuthManager.swift */; };
19C7AFD62B02584D003B35F2 /* KeychainStored.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7AFD52B02584D003B35F2 /* KeychainStored.swift */; };
FC2511A02B045C0A004717BC /* SignUpInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC25119F2B045C0A004717BC /* SignUpInteractor.swift */; };
FC2511A22B045C3F004717BC /* SignUpPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A12B045C3F004717BC /* SignUpPresenter.swift */; };
FC2511A42B045D6C004717BC /* SignUpModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A32B045D6C004717BC /* SignUpModels.swift */; };
FC2511A62B049020004717BC /* SignUpConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC2511A52B049020004717BC /* SignUpConfigurator.swift */; };
FC49758F2B03432800D8627F /* Pretendard-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */; };
FC4975932B03432800D8627F /* Pretendard-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */; };
FC4975942B03432800D8627F /* Pretendard-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */; };
Expand Down Expand Up @@ -82,6 +86,10 @@
194552122B03AFFC00299768 /* DummyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DummyViewController.swift; sourceTree = "<group>"; };
19C7AFCD2B02410F003B35F2 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = "<group>"; };
19C7AFD52B02584D003B35F2 /* KeychainStored.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainStored.swift; sourceTree = "<group>"; };
FC25119F2B045C0A004717BC /* SignUpInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpInteractor.swift; sourceTree = "<group>"; };
FC2511A12B045C3F004717BC /* SignUpPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpPresenter.swift; sourceTree = "<group>"; };
FC2511A32B045D6C004717BC /* SignUpModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpModels.swift; sourceTree = "<group>"; };
FC2511A52B049020004717BC /* SignUpConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpConfigurator.swift; sourceTree = "<group>"; };
FC4975862B03432700D8627F /* Pretendard-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-SemiBold.ttf"; sourceTree = "<group>"; };
FC49758A2B03432800D8627F /* Pretendard-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.ttf"; sourceTree = "<group>"; };
FC49758B2B03432800D8627F /* Pretendard-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.ttf"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -307,8 +315,8 @@
FC7E457B2AFF6F9D004F155A /* Scenes */ = {
isa = PBXGroup;
children = (
FCEE0FFB2B03AFAA00195BBE /* SingUpScene */,
1945520E2B03AEA400299768 /* Configurator.swift */,
FCEE0FFB2B03AFAA00195BBE /* SingUpScene */,
194552032B038FC400299768 /* Tabbar */,
194551EB2B037F1E00299768 /* Login */,
FC7E45912AFF747A004F155A /* DummyScene.swift */,
Expand Down Expand Up @@ -349,6 +357,10 @@
isa = PBXGroup;
children = (
FCEE0FF92B03AF8400195BBE /* SignUpViewController.swift */,
FC25119F2B045C0A004717BC /* SignUpInteractor.swift */,
FC2511A12B045C3F004717BC /* SignUpPresenter.swift */,
FC2511A32B045D6C004717BC /* SignUpModels.swift */,
FC2511A52B049020004717BC /* SignUpConfigurator.swift */,
);
path = SingUpScene;
sourceTree = "<group>";
Expand Down Expand Up @@ -496,13 +508,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FC2511A42B045D6C004717BC /* SignUpModels.swift in Sources */,
FC68E2A12B023326001AABFF /* EndPoint.swift in Sources */,
FC68E2A32B0233BC001AABFF /* NetworkError.swift in Sources */,
FC7E45962AFF7497004F155A /* DummyExtension.swift in Sources */,
1945520D2B0399E500299768 /* MainTabBarViewController.swift in Sources */,
194551F62B037F2D00299768 /* LoginViewController.swift in Sources */,
FC7E458E2AFF7462004F155A /* DummyService.swift in Sources */,
FCEE0FF22B036B6000195BBE /* LOButton.swift in Sources */,
FC2511A62B049020004717BC /* SignUpConfigurator.swift in Sources */,
194552132B03AFFC00299768 /* DummyViewController.swift in Sources */,
194551F22B037F2D00299768 /* LoginPresenter.swift in Sources */,
194552022B038B8300299768 /* OSLog+.swift in Sources */,
Expand All @@ -514,7 +528,9 @@
FC7E458A2AFF70FB004F155A /* ViewController.swift in Sources */,
FC7E453A2AFEB623004F155A /* AppDelegate.swift in Sources */,
FC68E29B2B02325D001AABFF /* Requestable.swift in Sources */,
FC2511A22B045C3F004717BC /* SignUpPresenter.swift in Sources */,
FC68E29D2B02326A001AABFF /* Responsable.swift in Sources */,
FC2511A02B045C0A004717BC /* SignUpInteractor.swift in Sources */,
19C7AFCE2B02410F003B35F2 /* AuthManager.swift in Sources */,
FC7E45902AFF746E004F155A /* DummyWorker.swift in Sources */,
1945520F2B03AEA400299768 /* Configurator.swift in Sources */,
Expand Down
58 changes: 17 additions & 41 deletions iOS/Layover/Layover/Scenes/SignUpViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,18 @@
// Layover
//
// Created by kong on 2023/11/14.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol SignUpDisplayLogic {
func displayNicknameValidation(response: Bool)
protocol SignUpDisplayLogic: AnyObject {
func displayNicknameValidation(response: SignUpModels.ValidateNickname.ViewModel)
func displayNickanmeDuplication()
}

final class SignUpViewController: UIViewController, SignUpDisplayLogic {

enum NicknameState {
case valid
case lessThan2GreaterThan8
case invalidCharacter

var alertDescription: String? {
switch self {
case .valid:
return nil
case .lessThan2GreaterThan8:
return "2자 이상 8자 이하로 입력해주세요."
case .invalidCharacter:
return "입력할 수 없는 문자입니다."
}
}
}

// MARK: - UI Components

private let titleLabel: UILabel = {
Expand Down Expand Up @@ -69,10 +54,13 @@ final class SignUpViewController: UIViewController, SignUpDisplayLogic {
return button
}()

var interactor: SignUpBusinessLogic?

// MARK: - Life Cycle

override func viewDidLoad() {
super.viewDidLoad()
SignUpConfigurator.sharedInstance.configure(self)
setUI()

// TODO: Base ViewController 로직으로 분리
Expand Down Expand Up @@ -116,7 +104,13 @@ final class SignUpViewController: UIViewController, SignUpDisplayLogic {

// MARK: - Custom Method

func displayNicknameValidation(response: Bool) {
func displayNicknameValidation(response: SignUpModels.ValidateNickname.ViewModel) {
nicknameAlertLabel.isHidden = response.canCheckDuplication
checkDuplicateNicknameButton.isEnabled = response.canCheckDuplication
nicknameAlertLabel.text = response.alertDescription
}

func displayNickanmeDuplication() {

}

Expand All @@ -125,31 +119,13 @@ final class SignUpViewController: UIViewController, SignUpDisplayLogic {
view.addGestureRecognizer(tapGesture)
}

private func validate(nickname: String) -> NicknameState {
if nickname.count < 2 || nickname.count > 8 {
return .lessThan2GreaterThan8
} else if nickname.wholeMatch(of: /^[a-zA-Z0-9-ㅎㅏ-ㅣ가-]+/) == nil {
return .invalidCharacter
}
return .valid
@objc private func setUpTextFieldState(_ sender: UITextField) {
guard let nickname = sender.text else { return }
interactor?.validateNickname(with: SignUpModels.ValidateNickname.Request(nickname: nickname))
}

@objc private func hideKeyboard(_ sender: Any) {
view.endEditing(true)
}

@objc private func setUpTextFieldState(_ sender: UITextField) {
guard let nickname = sender.text else { return }
let nicknameState = validate(nickname: nickname)
switch nicknameState {
case .valid:
nicknameAlertLabel.isHidden = true
checkDuplicateNicknameButton.isEnabled = true
case .lessThan2GreaterThan8, .invalidCharacter:
nicknameAlertLabel.isHidden = false
checkDuplicateNicknameButton.isEnabled = false
nicknameAlertLabel.text = nicknameState.alertDescription
}
}

}
26 changes: 26 additions & 0 deletions iOS/Layover/Layover/Scenes/SingUpScene/SignUpConfigurator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// SignUpConfigurator.swift
// Layover
//
// Created by kong on 2023/11/15.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import Foundation

final class SignUpConfigurator: Configurator {
typealias T = SignUpViewController

static let sharedInstance = SignUpConfigurator()

private init() { }

func configure(_ viewController: SignUpViewController) {
let viewController = viewController
let interactor = SignUpInteractor()
let presenter = SignUpPresenter()
viewController.interactor = interactor
interactor.presenter = presenter
presenter.viewController = viewController
}
}
41 changes: 41 additions & 0 deletions iOS/Layover/Layover/Scenes/SingUpScene/SignUpInteractor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// SignUpInteractor.swift
// Layover
//
// Created by kong on 2023/11/15.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol SignUpBusinessLogic {
func validateNickname(with request: SignUpModels.ValidateNickname.Request)
}

protocol SignUpDataStore { }

class SignUpInteractor: SignUpBusinessLogic, SignUpDataStore {

// MARK: - Properties

typealias Models = SignUpModels

var presenter: SignUpPresentationLogic?

// MARK: - UseCase: 닉네임 유효성 검사

func validateNickname(with request: SignUpModels.ValidateNickname.Request) {
let response = check(nickname: request.nickname)
presenter?.presentNicknameValidation(with: response)
}

private func check(nickname: String) -> SignUpModels.ValidateNickname.Response {
if nickname.count < 2 || nickname.count > 8 {
return .init(nicknameState: .lessThan2GreaterThan8)
} else if nickname.wholeMatch(of: /^[a-zA-Z0-9-ㅎㅏ-ㅣ가-]+/) == nil {
return .init(nicknameState: .invalidCharacter)
}
return .init(nicknameState: .valid)
}

}
45 changes: 45 additions & 0 deletions iOS/Layover/Layover/Scenes/SingUpScene/SignUpModels.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// SignUpModels.swift
// Layover
//
// Created by kong on 2023/11/15.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

enum SignUpModels {

// MARK: - Use Cases

enum ValidateNickname {
struct Request {
var nickname: String
}
struct Response {
var nicknameState: NicknameState
}
struct ViewModel {
var canCheckDuplication: Bool
var alertDescription: String?
}
}

// MARK: - State Type
enum NicknameState {
case valid
case lessThan2GreaterThan8
case invalidCharacter

var alertDescription: String? {
switch self {
case .valid:
return nil
case .lessThan2GreaterThan8:
return "2자 이상 8자 이하로 입력해주세요."
case .invalidCharacter:
return "입력할 수 없는 문자입니다."
}
}
}
}
30 changes: 30 additions & 0 deletions iOS/Layover/Layover/Scenes/SingUpScene/SignUpPresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// SignUpPresenter.swift
// Layover
//
// Created by kong on 2023/11/15.
// Copyright © 2023 CodeBomber. All rights reserved.
//

import UIKit

protocol SignUpPresentationLogic {
func presentNicknameValidation(with response: SignUpModels.ValidateNickname.Response)
}

class SignUpPresenter: SignUpPresentationLogic {

// MARK: - Properties

typealias Models = SignUpModels
weak var viewController: SignUpDisplayLogic?

// MARK: - UseCase: 닉네임 유효성 검사

func presentNicknameValidation(with response: SignUpModels.ValidateNickname.Response) {
let viewModel = Models.ValidateNickname.ViewModel(canCheckDuplication: response.nicknameState == .valid,
alertDescription: response.nicknameState.alertDescription)
viewController?.displayNicknameValidation(response: viewModel)
}

}

0 comments on commit c534805

Please sign in to comment.