diff --git a/README.md b/README.md
index 2d3aaf6..edc8b5f 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,17 @@
# swift-signup
-스위프트 회원가입 프로젝트
+## Step-1 회원가입 첫 번째 화면 만들기
+
+
+
+
+
+- 스토리보드로 화면 작성
+ - TextField의 KeyType, Button의 Enable 초기 설정 등
+- TextField의 Delegate 분리
+ - 타입을 만들어 Delegate를 구현해서, ViewController가 Delegate를 직접 채택하지 않도록 함
+- ID는 5~20자의 영문 소문자, 숫자와 특수기호(-, _)만 사용 가능
+- Password는 8~16자의 영문 대/소문자, 숫자, 특수문자를 조합해야 함
+- 이름은 꼭 입력해야 한다.
+- 모든 항목이 조건에 부합하면 버튼이 활성화된다.
+
+
diff --git a/swift-signup/swift-signup.xcodeproj/project.pbxproj b/swift-signup/swift-signup.xcodeproj/project.pbxproj
index 4c009c8..f6a3562 100644
--- a/swift-signup/swift-signup.xcodeproj/project.pbxproj
+++ b/swift-signup/swift-signup.xcodeproj/project.pbxproj
@@ -15,12 +15,14 @@
CE366BE02611BA8E00506D3F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE366BDE2611BA8E00506D3F /* LaunchScreen.storyboard */; };
CE366BEB2611BA8E00506D3F /* swift_signupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366BEA2611BA8E00506D3F /* swift_signupTests.swift */; };
CE366BF62611BA8E00506D3F /* swift_signupUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366BF52611BA8E00506D3F /* swift_signupUITests.swift */; };
- CE366C2C2611F9CF00506D3F /* IdTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C2B2611F9CF00506D3F /* IdTextField.swift */; };
- CE366C3426123A5A00506D3F /* PasswordTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C3326123A5A00506D3F /* PasswordTextField.swift */; };
- CE366C3F2612470800506D3F /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C3E2612470800506D3F /* CustomTextField.swift */; };
- CE366C5A2613495D00506D3F /* PasswordConfirmTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C592613495D00506D3F /* PasswordConfirmTextField.swift */; };
- CE366C622613EEDC00506D3F /* NameTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C612613EEDC00506D3F /* NameTextField.swift */; };
- CE366C6A261401E900506D3F /* ButtonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE366C69261401E900506D3F /* ButtonManager.swift */; };
+ CEA3A5422619B47C007AA664 /* CustomTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A5412619B47C007AA664 /* CustomTextFieldDelegate.swift */; };
+ CEA3A547261B26DB007AA664 /* Validater.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A546261B26DB007AA664 /* Validater.swift */; };
+ CEA3A54C261B2EE2007AA664 /* IdValidater.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A54B261B2EE2007AA664 /* IdValidater.swift */; };
+ CEA3A551261B2F0D007AA664 /* PasswordValidater.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A550261B2F0D007AA664 /* PasswordValidater.swift */; };
+ CEA3A556261B30E2007AA664 /* PasswordConfirmValidater.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A555261B30E2007AA664 /* PasswordConfirmValidater.swift */; };
+ CEA3A55B261B32DD007AA664 /* NameValidater.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A55A261B32DD007AA664 /* NameValidater.swift */; };
+ CEA3A560261B4E9A007AA664 /* Validable.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEA3A55F261B4E9A007AA664 /* Validable.swift */; };
+ CEB52F762616BEEC002C1650 /* PersonalInformationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB52F752616BEEC002C1650 /* PersonalInformationViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -55,12 +57,14 @@
CE366BF12611BA8E00506D3F /* swift-signupUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "swift-signupUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
CE366BF52611BA8E00506D3F /* swift_signupUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = swift_signupUITests.swift; sourceTree = ""; };
CE366BF72611BA8E00506D3F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- CE366C2B2611F9CF00506D3F /* IdTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdTextField.swift; sourceTree = ""; };
- CE366C3326123A5A00506D3F /* PasswordTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordTextField.swift; sourceTree = ""; };
- CE366C3E2612470800506D3F /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = ""; };
- CE366C592613495D00506D3F /* PasswordConfirmTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordConfirmTextField.swift; sourceTree = ""; };
- CE366C612613EEDC00506D3F /* NameTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameTextField.swift; sourceTree = ""; };
- CE366C69261401E900506D3F /* ButtonManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonManager.swift; sourceTree = ""; };
+ CEA3A5412619B47C007AA664 /* CustomTextFieldDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextFieldDelegate.swift; sourceTree = ""; };
+ CEA3A546261B26DB007AA664 /* Validater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validater.swift; sourceTree = ""; };
+ CEA3A54B261B2EE2007AA664 /* IdValidater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdValidater.swift; sourceTree = ""; };
+ CEA3A550261B2F0D007AA664 /* PasswordValidater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordValidater.swift; sourceTree = ""; };
+ CEA3A555261B30E2007AA664 /* PasswordConfirmValidater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordConfirmValidater.swift; sourceTree = ""; };
+ CEA3A55A261B32DD007AA664 /* NameValidater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameValidater.swift; sourceTree = ""; };
+ CEA3A55F261B4E9A007AA664 /* Validable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validable.swift; sourceTree = ""; };
+ CEB52F752616BEEC002C1650 /* PersonalInformationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalInformationViewController.swift; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -111,15 +115,11 @@
CE366BD22611BA8D00506D3F /* swift-signup */ = {
isa = PBXGroup;
children = (
+ CEB52F7F2616BF5E002C1650 /* Model */,
+ CEB52F7E2616BF05002C1650 /* TextFieldDelegate */,
+ CEB52F7D2616BEF7002C1650 /* Controller */,
CE366BD32611BA8D00506D3F /* AppDelegate.swift */,
CE366BD52611BA8D00506D3F /* SceneDelegate.swift */,
- CE366C69261401E900506D3F /* ButtonManager.swift */,
- CE366BD72611BA8D00506D3F /* ViewController.swift */,
- CE366C3E2612470800506D3F /* CustomTextField.swift */,
- CE366C2B2611F9CF00506D3F /* IdTextField.swift */,
- CE366C3326123A5A00506D3F /* PasswordTextField.swift */,
- CE366C592613495D00506D3F /* PasswordConfirmTextField.swift */,
- CE366C612613EEDC00506D3F /* NameTextField.swift */,
CE366BD92611BA8D00506D3F /* Main.storyboard */,
CE366BDC2611BA8E00506D3F /* Assets.xcassets */,
CE366BDE2611BA8E00506D3F /* LaunchScreen.storyboard */,
@@ -146,6 +146,36 @@
path = "swift-signupUITests";
sourceTree = "";
};
+ CEB52F7D2616BEF7002C1650 /* Controller */ = {
+ isa = PBXGroup;
+ children = (
+ CE366BD72611BA8D00506D3F /* ViewController.swift */,
+ CEB52F752616BEEC002C1650 /* PersonalInformationViewController.swift */,
+ );
+ path = Controller;
+ sourceTree = "";
+ };
+ CEB52F7E2616BF05002C1650 /* TextFieldDelegate */ = {
+ isa = PBXGroup;
+ children = (
+ CEA3A5412619B47C007AA664 /* CustomTextFieldDelegate.swift */,
+ );
+ path = TextFieldDelegate;
+ sourceTree = "";
+ };
+ CEB52F7F2616BF5E002C1650 /* Model */ = {
+ isa = PBXGroup;
+ children = (
+ CEA3A546261B26DB007AA664 /* Validater.swift */,
+ CEA3A54B261B2EE2007AA664 /* IdValidater.swift */,
+ CEA3A550261B2F0D007AA664 /* PasswordValidater.swift */,
+ CEA3A555261B30E2007AA664 /* PasswordConfirmValidater.swift */,
+ CEA3A55A261B32DD007AA664 /* NameValidater.swift */,
+ CEA3A55F261B4E9A007AA664 /* Validable.swift */,
+ );
+ path = Model;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -276,15 +306,17 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- CE366C622613EEDC00506D3F /* NameTextField.swift in Sources */,
- CE366C3426123A5A00506D3F /* PasswordTextField.swift in Sources */,
+ CEA3A55B261B32DD007AA664 /* NameValidater.swift in Sources */,
CE366BD82611BA8D00506D3F /* ViewController.swift in Sources */,
- CE366C3F2612470800506D3F /* CustomTextField.swift in Sources */,
+ CEB52F762616BEEC002C1650 /* PersonalInformationViewController.swift in Sources */,
CE366BD42611BA8D00506D3F /* AppDelegate.swift in Sources */,
- CE366C5A2613495D00506D3F /* PasswordConfirmTextField.swift in Sources */,
- CE366C2C2611F9CF00506D3F /* IdTextField.swift in Sources */,
+ CEA3A54C261B2EE2007AA664 /* IdValidater.swift in Sources */,
+ CEA3A551261B2F0D007AA664 /* PasswordValidater.swift in Sources */,
+ CEA3A556261B30E2007AA664 /* PasswordConfirmValidater.swift in Sources */,
+ CEA3A5422619B47C007AA664 /* CustomTextFieldDelegate.swift in Sources */,
CE366BD62611BA8D00506D3F /* SceneDelegate.swift in Sources */,
- CE366C6A261401E900506D3F /* ButtonManager.swift in Sources */,
+ CEA3A547261B26DB007AA664 /* Validater.swift in Sources */,
+ CEA3A560261B4E9A007AA664 /* Validable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/swift-signup/swift-signup.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate b/swift-signup/swift-signup.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate
index 36f18ff..7d86e58 100644
Binary files a/swift-signup/swift-signup.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate and b/swift-signup/swift-signup.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/swift-signup/swift-signup/Base.lproj/Main.storyboard b/swift-signup/swift-signup/Base.lproj/Main.storyboard
index 4dc9534..6e21850 100644
--- a/swift-signup/swift-signup/Base.lproj/Main.storyboard
+++ b/swift-signup/swift-signup/Base.lproj/Main.storyboard
@@ -1,5 +1,5 @@
-
+
@@ -26,37 +26,49 @@
-
+
-
+
+
+
+
-
+
-
+
+
+
+
-
+
-
+
+
+
+
-
+
-
+
+
+
+
@@ -92,7 +104,7 @@
-
+
@@ -105,6 +117,9 @@
+
+
+
@@ -183,25 +198,223 @@
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/swift-signup/swift-signup/ButtonManager.swift b/swift-signup/swift-signup/ButtonManager.swift
deleted file mode 100644
index abaeda0..0000000
--- a/swift-signup/swift-signup/ButtonManager.swift
+++ /dev/null
@@ -1,39 +0,0 @@
-
-import Foundation
-import UIKit
-
-class ButtonManager {
- private var states : [ObjectIdentifier:CustomTextField.State]
- private var activeButton : Bool
-
- init() {
- self.states = [:]
- self.activeButton = false
- allElementsStateValid()
- }
-
- func update(textField: CustomTextField.Type, state: CustomTextField.State) {
- self.states.updateValue(state, forKey: ObjectIdentifier(textField))
- allElementsStateValid()
- }
-
- func allElementsStateValid() {
- for ( _, state) in self.states {
- if state != .end && state != .valid {
- self.activeButton = false
- break
- }
- self.activeButton = true
- }
-
- NotificationCenter.default.post(name: ButtonManager.buttonState, object: self, userInfo: [ButtonManager.Info.state : self.activeButton])
- }
-}
-
-extension ButtonManager {
- enum Info {
- case state
- }
-
- static let buttonState = Notification.Name("buttonState")
-}
diff --git a/swift-signup/swift-signup/Controller/PersonalInformationViewController.swift b/swift-signup/swift-signup/Controller/PersonalInformationViewController.swift
new file mode 100644
index 0000000..0647a06
--- /dev/null
+++ b/swift-signup/swift-signup/Controller/PersonalInformationViewController.swift
@@ -0,0 +1,16 @@
+
+import Foundation
+import UIKit
+
+class PersonnalInformationViewController : UIViewController {
+
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ }
+
+ @IBAction func previousButtonPressed(_ sender: Any) {
+ self.navigationController?.popViewController(animated: true)
+ }
+}
+
diff --git a/swift-signup/swift-signup/Controller/ViewController.swift b/swift-signup/swift-signup/Controller/ViewController.swift
new file mode 100644
index 0000000..6d043f0
--- /dev/null
+++ b/swift-signup/swift-signup/Controller/ViewController.swift
@@ -0,0 +1,156 @@
+
+import UIKit
+
+class ViewController: UIViewController {
+
+ @IBOutlet weak var nextButton: UIButton!
+
+ @IBOutlet weak var idTextField: UITextField!
+ @IBOutlet weak var idLabel: UILabel!
+
+ @IBOutlet weak var passwordTextField: UITextField!
+ @IBOutlet weak var passwordLabel: UILabel!
+
+ @IBOutlet weak var passwordConfirmTextField: UITextField!
+ @IBOutlet weak var passwordConfirmLabel: UILabel!
+
+ @IBOutlet weak var nameTextField: UITextField!
+ @IBOutlet weak var nameLabel: UILabel!
+
+ private var validater = Validater()
+ private var idTextFieldDelegate = CustomTextFieldDelegate()
+ private var passwordTextFieldDelegate = CustomTextFieldDelegate()
+ private var passwordConfirmTextFieldDelegate = CustomTextFieldDelegate()
+ private var nameTextFieldDelegate = CustomTextFieldDelegate()
+
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+
+ NotificationCenter.default.addObserver(self, selector: #selector(idGuideText), name: Validater.evaluatedIdInformation, object: validater)
+ NotificationCenter.default.addObserver(self, selector: #selector(passwordGuideText), name: Validater.evaluatedPasswordInformation, object: validater)
+ NotificationCenter.default.addObserver(self, selector: #selector(passwordConfirmGuideText), name: Validater.evaluatedPasswordConfirmInformation, object: validater)
+ NotificationCenter.default.addObserver(self, selector: #selector(nameGuideText), name: Validater.evaluatedNameInformation, object: validater)
+ NotificationCenter.default.addObserver(self, selector: #selector(buttonState), name: Validater.isButtonValid, object: validater)
+
+ configureDelegate()
+ configureTextField()
+ }
+
+ //MARK: configure
+ func configureDelegate() {
+ self.idTextField.delegate = idTextFieldDelegate
+ self.passwordTextField.delegate = passwordTextFieldDelegate
+ self.passwordConfirmTextField.delegate = passwordConfirmTextFieldDelegate
+ self.nameTextField.delegate = nameTextFieldDelegate
+ }
+
+ func configureTextField() {
+ self.idTextFieldDelegate.configureText() { text, range, string in
+ self.validater.idValidate(text: text, range: range, string: string)
+ }
+
+ self.passwordTextFieldDelegate.configureText() { text, range, string in
+ self.validater.passwordValidate(text: text, range: range, string: string)
+ }
+
+ self.passwordConfirmTextFieldDelegate.configureText() { text, range, string in
+ self.validater.passwordConfirmValidate(text: text, range: range, string: string)
+ }
+
+ self.nameTextFieldDelegate.configureText() { text, range, string in
+ self.validater.nameValidate(text: text, range: range, string: string)
+ }
+ }
+
+ //MARK: @objc 처리
+ @objc
+ func idGuideText(notification: Notification) {
+ guard let text = notification.userInfo?[Validater.MessageInfo.text] as? String,
+ let color = notification.userInfo?[Validater.MessageInfo.color] as? UIColor
+ else {
+ return
+ }
+ self.idLabel.text = text
+ self.idLabel.textColor = color
+ self.idTextField.layer.borderColor = color.cgColor
+ }
+
+ @objc
+ func passwordGuideText(notification: Notification) {
+ guard let text = notification.userInfo?[Validater.MessageInfo.text] as? String,
+ let color = notification.userInfo?[Validater.MessageInfo.color] as? UIColor
+ else {
+ return
+ }
+ self.passwordLabel.text = text
+ self.passwordLabel.textColor = color
+ self.passwordTextField.layer.borderColor = color.cgColor
+ }
+
+ @objc
+ func passwordConfirmGuideText(notification: Notification) {
+ guard let text = notification.userInfo?[Validater.MessageInfo.text] as? String,
+ let color = notification.userInfo?[Validater.MessageInfo.color] as? UIColor
+ else {
+ return
+ }
+ self.passwordConfirmLabel.text = text
+ self.passwordConfirmLabel.textColor = color
+ self.passwordConfirmTextField.layer.borderColor = color.cgColor
+ }
+
+ @objc
+ func nameGuideText(notification: Notification) {
+ guard let text = notification.userInfo?[Validater.MessageInfo.text] as? String,
+ let color = notification.userInfo?[Validater.MessageInfo.color] as? UIColor
+ else {
+ return
+ }
+ self.nameLabel.text = text
+ self.nameLabel.textColor = color
+ self.nameTextField.layer.borderColor = color.cgColor
+ }
+
+ @objc
+ func buttonState(notification: Notification) {
+ guard let isValid = notification.userInfo?[Validater.TextStateInfo.isAllValid] as? Bool
+ else {
+ return
+ }
+ self.nextButton.isEnabled = isValid
+ }
+
+ //MARK: Responder 처리
+ @IBAction func exitIdTextField(_ sender: Any) {
+ self.passwordTextField.becomeFirstResponder()
+ }
+
+
+ @IBAction func exitPasswordTextField(_ sender: Any) {
+ self.passwordConfirmTextField.becomeFirstResponder()
+ }
+
+
+ @IBAction func exitPasswordConfirmTextField(_ sender: Any) {
+ self.nameTextField.becomeFirstResponder()
+ }
+
+ @IBAction func exitNameTextField(_ sender: Any) {
+ self.nameTextField.resignFirstResponder()
+ if self.nextButton.isEnabled, let personnalInformationViewController = self.storyboard?.instantiateViewController(identifier: "PersonnalInformationViewController") {
+ navigationController?.pushViewController(personnalInformationViewController, animated: true)
+ }
+ }
+
+ @IBAction func nextButtonPressed(_ sender: Any) {
+ self.nameTextField.resignFirstResponder()
+ guard let personnalInformationViewController = self.storyboard?.instantiateViewController(identifier: "PersonnalInformationViewController")
+ else {
+ return
+ }
+ navigationController?.pushViewController(personnalInformationViewController, animated: true)
+ }
+}
+
diff --git a/swift-signup/swift-signup/CustomTextField.swift b/swift-signup/swift-signup/CustomTextField.swift
deleted file mode 100644
index c127a6b..0000000
--- a/swift-signup/swift-signup/CustomTextField.swift
+++ /dev/null
@@ -1,72 +0,0 @@
-
-import Foundation
-import UIKit
-
-class CustomTextField : UITextField, UITextFieldDelegate {
-
- enum State {
- case begin
- case valid
- case invalid
- case end
- }
-
- var currentState : State!
-
- override init(frame: CGRect) {
- super.init(frame: frame)
- self.currentState = .begin
- self.layer.borderWidth = 1.0
- stateToColor()
- }
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
- self.currentState = .begin
- self.layer.borderWidth = 1.0
- stateToColor()
- }
-
- //MARK: 상태에 따라 텍스트필드 테두리 색 변경
- func stateToColor() {
- switch self.currentState {
- case .begin:
- self.layer.borderColor = UIColor.systemGray3.cgColor
- case .valid:
- self.layer.borderColor = UIColor.systemGreen.cgColor
- case .invalid:
- self.layer.borderColor = UIColor.red.cgColor
- case .end:
- self.layer.borderColor = UIColor.systemGray3.cgColor
- default:
- return
- }
- }
-
- //MARK: 선택이 되면 파란색 테두리
- func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
- self.layer.borderColor = UIColor.systemBlue.cgColor
- return true
- }
-
- //MARK: 선택이 끝나면 상태에 따라 테두리 색 변경
- func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
- if self.currentState == .valid || self.currentState == .end {
- self.currentState = .end
- }
- stateToColor()
- return true
- }
-}
-
-extension CustomTextField {
- enum MessageInfo {
- case text
- case color
- }
-
- static let idState = Notification.Name("idState")
- static let passwordState = Notification.Name("passwordState")
- static let passwordConfirmState = Notification.Name("passwordConfirmState")
- static let nameState = Notification.Name("nameState")
-}
diff --git a/swift-signup/swift-signup/IdTextField.swift b/swift-signup/swift-signup/IdTextField.swift
deleted file mode 100644
index b365e2b..0000000
--- a/swift-signup/swift-signup/IdTextField.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-
-import Foundation
-import UIKit
-
-class IdTextField : CustomTextField {
-
- func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
- let text = (textField.text ?? "") as NSString
- let newText = text.replacingCharacters(in: range, with: string)
-
- isValid(id: newText)
- stateToColor()
- return true
- }
-
- func isValid(id: String) {
- let idRegularExpression = "[a-z0-9_-]{5,20}"
- let validString = NSPredicate(format: "SELF MATCHES %@", idRegularExpression)
-
- var info : [AnyHashable:Any] = [:]
-
- if validString.evaluate(with: id) {
- info.updateValue("사용 가능한 아이디입니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.systemGreen, forKey: MessageInfo.color)
- self.currentState = .valid
- } else {
- info.updateValue("5~20자의 영문 소문자, 숫자와 특수기호(_)(-)만 사용 가능합니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- }
- NotificationCenter.default.post(name: CustomTextField.idState, object: self, userInfo: info)
-
- }
-}
diff --git a/swift-signup/swift-signup/Model/IdValidater.swift b/swift-signup/swift-signup/Model/IdValidater.swift
new file mode 100644
index 0000000..720305a
--- /dev/null
+++ b/swift-signup/swift-signup/Model/IdValidater.swift
@@ -0,0 +1,35 @@
+
+import Foundation
+import UIKit
+
+class IdValidater : Validable {
+
+ private var currentState: TextState
+
+ init() {
+ self.currentState = .begin
+ }
+
+ func evaluate(with text: String) -> [AnyHashable:Any] {
+ let idRegularExpression = "[a-z0-9_-]{5,20}"
+ let validString = NSPredicate(format: "SELF MATCHES %@", idRegularExpression)
+
+ var messageInfo : [AnyHashable:Any] = [:]
+
+ if validString.evaluate(with: text) {
+ messageInfo.updateValue("사용 가능한 아이디입니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.systemGreen, forKey: Validater.MessageInfo.color)
+ self.currentState = .valid
+ } else {
+ messageInfo.updateValue("5~20자의 영문 소문자, 숫자와 특수기호(_)(-)만 사용 가능합니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+
+ return messageInfo
+ }
+
+ func state() -> TextState {
+ return self.currentState
+ }
+}
diff --git a/swift-signup/swift-signup/Model/NameValidater.swift b/swift-signup/swift-signup/Model/NameValidater.swift
new file mode 100644
index 0000000..7fa652f
--- /dev/null
+++ b/swift-signup/swift-signup/Model/NameValidater.swift
@@ -0,0 +1,33 @@
+
+import Foundation
+import UIKit
+
+class NameValidater : Validable {
+
+ private var currentState: TextState
+
+ init() {
+ self.currentState = .begin
+ }
+
+ func evaluate(with text: String) -> [AnyHashable:Any] {
+
+ var messageInfo : [AnyHashable:Any] = [:]
+
+ if text == "" {
+ messageInfo.updateValue("이름은 필수 입력 항목입니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ } else {
+ messageInfo.updateValue("", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.systemGreen, forKey: Validater.MessageInfo.color)
+ self.currentState = .valid
+ }
+
+ return messageInfo
+ }
+
+ func state() -> TextState {
+ return self.currentState
+ }
+}
diff --git a/swift-signup/swift-signup/Model/PasswordConfirmValidater.swift b/swift-signup/swift-signup/Model/PasswordConfirmValidater.swift
new file mode 100644
index 0000000..6f7a8ff
--- /dev/null
+++ b/swift-signup/swift-signup/Model/PasswordConfirmValidater.swift
@@ -0,0 +1,43 @@
+
+import Foundation
+import UIKit
+
+class PasswordConfirmValidater : Validable {
+
+ private var currentState: TextState
+ private var password: String
+
+ init() {
+ self.currentState = .begin
+ self.password = ""
+ }
+
+ func evaluate(with text: String) -> [AnyHashable:Any] {
+
+ var messageInfo : [AnyHashable:Any] = [:]
+
+ if isEqual(password: text) {
+ messageInfo.updateValue("비밀번호가 일치합니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.systemGreen, forKey: Validater.MessageInfo.color)
+ self.currentState = .valid
+ } else {
+ messageInfo.updateValue("비밀번호가 일치하지 않습니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+
+ return messageInfo
+ }
+
+ func update(password: String) {
+ self.password = password
+ }
+
+ func isEqual(password: String) -> Bool {
+ return self.password == password
+ }
+
+ func state() -> TextState {
+ return self.currentState
+ }
+}
diff --git a/swift-signup/swift-signup/Model/PasswordValidater.swift b/swift-signup/swift-signup/Model/PasswordValidater.swift
new file mode 100644
index 0000000..2a04e9c
--- /dev/null
+++ b/swift-signup/swift-signup/Model/PasswordValidater.swift
@@ -0,0 +1,63 @@
+
+import Foundation
+import UIKit
+
+class PasswordValidater : Validable {
+
+ private var currentState: TextState
+
+ init() {
+ self.currentState = .begin
+ }
+
+ func evaluate(with text: String) -> [AnyHashable:Any] {
+ let capitalRegularExpression = "[A-Z]+"
+ let numberRegularExpression = "[0-9]+"
+ let specialRegularExpression = "[!@#$%^&*()_+=-]+"
+
+ var messageInfo : [AnyHashable:Any] = [:]
+
+ if text.count < 8 || text.count > 16
+ {
+ messageInfo.updateValue("8자 이상 16자 이하로 입력해주세요.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+ else if match(regularExpression: capitalRegularExpression, with: text) == false
+ {
+ messageInfo.updateValue("영문 대문자를 최소 1자 이상 포함해주세요.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+ else if match(regularExpression: numberRegularExpression, with: text) == false
+ {
+ messageInfo.updateValue("숫자를 최소 1자 이상 포함해주세요.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+ else if match(regularExpression: specialRegularExpression, with: text) == false
+ {
+ messageInfo.updateValue("특수문자를 최소 1자 이상 포함해주세요.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.red, forKey: Validater.MessageInfo.color)
+ self.currentState = .invalid
+ }
+ else
+ {
+ messageInfo.updateValue("안전한 비밀번호입니다.", forKey: Validater.MessageInfo.text)
+ messageInfo.updateValue(UIColor.systemGreen, forKey: Validater.MessageInfo.color)
+ self.currentState = .valid
+ }
+
+ return messageInfo
+ }
+
+ func match(regularExpression: String, with string: String) -> Bool {
+ let validString = try? NSRegularExpression(pattern: regularExpression, options: [])
+
+ return validString?.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.count)) != nil
+ }
+
+ func state() -> TextState {
+ return self.currentState
+ }
+}
diff --git a/swift-signup/swift-signup/Model/Validable.swift b/swift-signup/swift-signup/Model/Validable.swift
new file mode 100644
index 0000000..96f9236
--- /dev/null
+++ b/swift-signup/swift-signup/Model/Validable.swift
@@ -0,0 +1,12 @@
+
+import Foundation
+
+enum TextState {
+ case begin
+ case valid
+ case invalid
+}
+
+protocol Validable {
+ func state() -> TextState
+}
diff --git a/swift-signup/swift-signup/Model/Validater.swift b/swift-signup/swift-signup/Model/Validater.swift
new file mode 100644
index 0000000..2b30f91
--- /dev/null
+++ b/swift-signup/swift-signup/Model/Validater.swift
@@ -0,0 +1,83 @@
+
+import Foundation
+import UIKit
+
+class Validater {
+ private var idValidater: IdValidater
+ private var passwordValidater: PasswordValidater
+ private var passwordConfirmValidater: PasswordConfirmValidater
+ private var nameValidater: NameValidater
+
+ init() {
+ self.idValidater = IdValidater()
+ self.passwordValidater = PasswordValidater()
+ self.passwordConfirmValidater = PasswordConfirmValidater()
+ self.nameValidater = NameValidater()
+ }
+
+ func combineText(text: String, range: NSRange, string: String) -> String {
+ let newText = text as NSString
+ return newText.replacingCharacters(in: range, with: string)
+ }
+
+ func idValidate(text: String, range: NSRange, string: String) {
+ let newText = combineText(text: text, range: range, string: string)
+ let messageInfo = self.idValidater.evaluate(with: newText)
+ NotificationCenter.default.post(name: Validater.evaluatedIdInformation, object: self, userInfo: messageInfo)
+ buttonValidate()
+ }
+
+ func passwordValidate(text: String, range: NSRange, string: String) {
+ let newText = combineText(text: text, range: range, string: string)
+ self.passwordConfirmValidater.update(password: newText)
+ let messageInfo = self.passwordValidater.evaluate(with: newText)
+ NotificationCenter.default.post(name: Validater.evaluatedPasswordInformation, object: self, userInfo: messageInfo)
+ buttonValidate()
+ }
+
+ func passwordConfirmValidate(text: String, range: NSRange, string: String) {
+ let newText = combineText(text: text, range: range, string: string)
+ let messageInfo = self.passwordConfirmValidater.evaluate(with: newText)
+ NotificationCenter.default.post(name: Validater.evaluatedPasswordConfirmInformation, object: self, userInfo: messageInfo)
+ buttonValidate()
+ }
+
+ func nameValidate(text: String, range: NSRange, string: String) {
+ let newText = combineText(text: text, range: range, string: string)
+ let messageInfo = self.nameValidater.evaluate(with: newText)
+ NotificationCenter.default.post(name: Validater.evaluatedNameInformation, object: self, userInfo: messageInfo)
+ buttonValidate()
+ }
+
+ func buttonValidate() {
+ var isAllValid : Bool
+ if self.idValidater.state() == .valid, self.passwordValidater.state() == .valid,
+ self.passwordConfirmValidater.state() == .valid, self.nameValidater.state() == .valid {
+ isAllValid = true
+ } else {
+ isAllValid = false
+ }
+ NotificationCenter.default.post(name: Validater.isButtonValid, object: self, userInfo: [Validater.TextStateInfo.isAllValid : isAllValid])
+ }
+}
+
+extension Validater {
+
+ enum MessageInfo {
+ case text
+ case color
+ }
+
+ enum TextStateInfo {
+ case isAllValid
+ }
+
+ static let evaluatedIdInformation = Notification.Name("valiatedIdInformation")
+ static let evaluatedPasswordInformation = Notification.Name("evaluatedPasswordInformation")
+ static let evaluatedPasswordConfirmInformation = Notification.Name("evaluatedPasswordConfirmInformation")
+ static let evaluatedNameInformation = Notification.Name("evaluatedNameInformation")
+ static let isButtonValid = Notification.Name("isButtonValid")
+
+}
+
+
diff --git a/swift-signup/swift-signup/NameTextField.swift b/swift-signup/swift-signup/NameTextField.swift
deleted file mode 100644
index 4de0f53..0000000
--- a/swift-signup/swift-signup/NameTextField.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-
-import Foundation
-import UIKit
-
-class NameTextField : CustomTextField {
-
- func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
- let text = (textField.text ?? "") as NSString
- let newText = text.replacingCharacters(in: range, with: string)
-
- isValidId(string: newText)
- stateToColor()
- return true
- }
-
- func isValidId(string: String) {
- var info : [AnyHashable:Any] = [:]
-
- if string.isEmpty {
- info.updateValue("이름은 필수 입력 항목입니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- } else {
- info.updateValue("", forKey: MessageInfo.text)
- info.updateValue(UIColor.systemGreen, forKey: MessageInfo.color)
- self.currentState = .valid
- }
-
- NotificationCenter.default.post(name: CustomTextField.nameState, object: self, userInfo: info)
- }
-}
diff --git a/swift-signup/swift-signup/PasswordConfirmTextField.swift b/swift-signup/swift-signup/PasswordConfirmTextField.swift
deleted file mode 100644
index 823fdc1..0000000
--- a/swift-signup/swift-signup/PasswordConfirmTextField.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-
-import Foundation
-import UIKit
-
-class PasswordConfirmTextField : CustomTextField {
-
- private var password : String
-
- override init(frame: CGRect) {
- self.password = ""
- super.init(frame: frame)
- self.isSecureTextEntry = true
- }
-
- required init?(coder: NSCoder) {
- self.password = ""
- super.init(coder: coder)
- self.isSecureTextEntry = true
- }
-
- func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
- let text = (textField.text ?? "") as NSString
- let newText = text.replacingCharacters(in: range, with: string)
-
- isValid(password: newText)
- stateToColor()
- return true
- }
-
- func isValid(password: String) {
- var info : [AnyHashable:Any] = [:]
-
- if self.password == password {
- self.currentState = .valid
- info.updateValue("비밀번호가 일치합니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.systemGreen, forKey: MessageInfo.color)
- }
- else {
- self.currentState = .invalid
- info.updateValue("비밀번호가 일치하지 않습니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- }
-
- NotificationCenter.default.post(name: CustomTextField.passwordConfirmState, object: self, userInfo: info)
- }
-
- func update(password: String) {
- self.password = password
- }
-
-
-}
diff --git a/swift-signup/swift-signup/PasswordTextField.swift b/swift-signup/swift-signup/PasswordTextField.swift
deleted file mode 100644
index 71b6d9e..0000000
--- a/swift-signup/swift-signup/PasswordTextField.swift
+++ /dev/null
@@ -1,83 +0,0 @@
-
-import Foundation
-import UIKit
-
-class PasswordTextField : CustomTextField {
-
- override init(frame: CGRect) {
- super.init(frame: frame)
- self.isSecureTextEntry = true
- }
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
- self.isSecureTextEntry = true
- }
-
- func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
- let text = (textField.text ?? "") as NSString
- let newText = text.replacingCharacters(in: range, with: string)
-
- isValid(password: newText)
- stateToColor()
- return true
- }
-
- func isValid(password: String) {
- let capitalRegularExpression = "[A-Z]+"
- let numberRegularExpression = "[0-9]+"
- let specialRegularExpression = "[!@#$%^&*()_+=-]+"
-
- var info : [AnyHashable:Any] = [:]
-
- if password.count < 8 || password.count > 16 {
- info.updateValue("8자 이상 16자 이하로 입력해주세요.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- }
- else if evaluate(regularExpression: capitalRegularExpression, with: password) == false
- {
- info.updateValue("영문 대문자를 최소 1자 이상 포함해주세요.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- }
- else if evaluate(regularExpression: numberRegularExpression, with: password) == false
- {
- info.updateValue("숫자를 최소 1자 이상 포함해주세요.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- }
- else if evaluate(regularExpression: specialRegularExpression, with: password) == false
- {
- info.updateValue("특수문자를 최소 1자 이상 포함해주세요.", forKey: MessageInfo.text)
- info.updateValue(UIColor.red, forKey: MessageInfo.color)
- self.currentState = .invalid
- }
- else
- {
- info.updateValue("안전한 비밀번호입니다.", forKey: MessageInfo.text)
- info.updateValue(UIColor.systemGreen, forKey: MessageInfo.color)
- self.currentState = .valid
- }
-
- info.updateValue(password, forKey: UserInfo.password)
- NotificationCenter.default.post(name: CustomTextField.passwordState, object: self, userInfo: info)
- }
-
- func evaluate(regularExpression: String, with string: String) -> Bool {
- let validString = try? NSRegularExpression(pattern: regularExpression, options: [])
-
- if validString?.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.count)) != nil {
- return true
- } else {
- return false
- }
-
- }
-}
-
-extension PasswordTextField {
- enum UserInfo {
- case password
- }
-}
diff --git a/swift-signup/swift-signup/TextFieldDelegate/CustomTextFieldDelegate.swift b/swift-signup/swift-signup/TextFieldDelegate/CustomTextFieldDelegate.swift
new file mode 100644
index 0000000..cd76201
--- /dev/null
+++ b/swift-signup/swift-signup/TextFieldDelegate/CustomTextFieldDelegate.swift
@@ -0,0 +1,22 @@
+
+import Foundation
+import UIKit
+
+class CustomTextFieldDelegate : NSObject, UITextFieldDelegate {
+
+ private var text : ((String, NSRange, String) -> Void)!
+
+ func textFieldDidBeginEditing(_ textField: UITextField) {
+ textField.layer.borderWidth = 1.0
+ textField.layer.borderColor = UIColor.systemBlue.cgColor
+ }
+
+ func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
+ self.text(textField.text ?? "", range, string)
+ return true
+ }
+
+ func configureText(closure: @escaping ((String, NSRange, String) -> Void)) {
+ self.text = closure
+ }
+}
diff --git a/swift-signup/swift-signup/ViewController.swift b/swift-signup/swift-signup/ViewController.swift
deleted file mode 100644
index 73b9793..0000000
--- a/swift-signup/swift-signup/ViewController.swift
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-// ViewController.swift
-// swift-signup
-//
-// Created by user on 2021/03/29.
-//
-
-import UIKit
-
-class ViewController: UIViewController {
-
-
- @IBOutlet weak var idText: IdTextField!
- @IBOutlet weak var idLabel: UILabel!
-
- @IBOutlet weak var passwordText: PasswordTextField!
- @IBOutlet weak var passwordLabel: UILabel!
-
- @IBOutlet weak var passwordConfirmText: PasswordConfirmTextField!
- @IBOutlet weak var passwordConfirmLabel: UILabel!
-
- @IBOutlet weak var nameText: NameTextField!
- @IBOutlet weak var nameLabel: UILabel!
-
- @IBOutlet weak var nextButton: UIButton!
- private var buttonManager = ButtonManager()
-
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do any additional setup after loading the view.
-
- NotificationCenter.default.addObserver(self, selector: #selector(idGuideText), name: CustomTextField.idState, object: idText)
- NotificationCenter.default.addObserver(self, selector: #selector(passwordGuideText), name: CustomTextField.passwordState, object: passwordText)
- NotificationCenter.default.addObserver(self, selector: #selector(passwordConfirmGuideText), name: CustomTextField.passwordConfirmState, object: passwordConfirmText)
- NotificationCenter.default.addObserver(self, selector: #selector(nameGuideText), name: CustomTextField.nameState, object: nameText)
- NotificationCenter.default.addObserver(self, selector: #selector(buttonState), name: ButtonManager.buttonState, object: buttonManager)
-
- registerDelegate()
- registerTextField()
- }
-
- func registerDelegate() {
- self.idText.delegate = idText
- self.passwordText.delegate = passwordText
- self.passwordConfirmText.delegate = passwordConfirmText
- self.nameText.delegate = nameText
- }
-
- func registerTextField() {
- self.buttonManager.update(textField: type(of: idText), state: idText.currentState)
- self.buttonManager.update(textField: type(of: passwordText), state: passwordText.currentState)
- self.buttonManager.update(textField: type(of: passwordConfirmText), state: passwordConfirmText.currentState)
- self.buttonManager.update(textField: type(of: nameText), state: nameText.currentState)
- }
-
- //MARK: @objc 처리
- @objc
- func idGuideText(notification: Notification) {
- guard let text = notification.userInfo?[CustomTextField.MessageInfo.text] as? String,
- let color = notification.userInfo?[CustomTextField.MessageInfo.color] as? UIColor
- else {
- return
- }
- self.idLabel.text = text
- self.idLabel.textColor = color
- buttonManager.update(textField: type(of: idText), state: idText.currentState)
- }
-
- @objc
- func passwordGuideText(notification: Notification) {
- guard let text = notification.userInfo?[CustomTextField.MessageInfo.text] as? String,
- let color = notification.userInfo?[CustomTextField.MessageInfo.color] as? UIColor,
- let password = notification.userInfo?[PasswordTextField.UserInfo.password] as? String
- else {
- return
- }
- self.passwordLabel.text = text
- self.passwordLabel.textColor = color
- self.passwordConfirmText.update(password: password)
- buttonManager.update(textField: type(of: passwordText), state: passwordText.currentState)
- }
-
- @objc
- func passwordConfirmGuideText(notification: Notification) {
- guard let text = notification.userInfo?[CustomTextField.MessageInfo.text] as? String,
- let color = notification.userInfo?[CustomTextField.MessageInfo.color] as? UIColor
- else {
- return
- }
- self.passwordConfirmLabel.text = text
- self.passwordConfirmLabel.textColor = color
- buttonManager.update(textField: type(of: passwordConfirmText), state: passwordConfirmText.currentState)
- }
-
- @objc
- func nameGuideText(notification: Notification) {
- guard let text = notification.userInfo?[CustomTextField.MessageInfo.text] as? String,
- let color = notification.userInfo?[CustomTextField.MessageInfo.color] as? UIColor
- else {
- return
- }
- self.nameLabel.text = text
- self.nameLabel.textColor = color
- buttonManager.update(textField: type(of: nameText), state: nameText.currentState)
- }
-
- @objc
- func buttonState(notification: Notification) {
- guard let isActive = notification.userInfo?[ButtonManager.Info.state] as? Bool
- else {
- return
- }
- self.nextButton.isEnabled = isActive
- }
-
-}
-