diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..3d924b3 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 2d3aaf6..09129c0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # swift-signup -스위프트 회원가입 프로젝트 +![](https://images.velog.io/images/panther222128/post/b3caa6f8-7419-430b-ba82-fac83acea94b/ezgif.com-video-to-gif.gif) + + diff --git a/SignUpApp/SignUpApp.xcodeproj/project.pbxproj b/SignUpApp/SignUpApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ecd5fab --- /dev/null +++ b/SignUpApp/SignUpApp.xcodeproj/project.pbxproj @@ -0,0 +1,484 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + A01ADE9F2614541200C30356 /* IDTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01ADE9E2614541200C30356 /* IDTextFieldDelegate.swift */; }; + A01ADEA32614545E00C30356 /* PasswordTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01ADEA22614545E00C30356 /* PasswordTextFieldDelegate.swift */; }; + A01ADEA62614546C00C30356 /* CheckPasswordTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01ADEA52614546C00C30356 /* CheckPasswordTextFieldDelegate.swift */; }; + A01ADEA92614547900C30356 /* UserNameTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A01ADEA82614547900C30356 /* UserNameTextFieldDelegate.swift */; }; + A07C89AB2618554F00DD3C4B /* PasswordCheckMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A07C89AA2618554F00DD3C4B /* PasswordCheckMessage.swift */; }; + A09160B3261973B60014C3B9 /* IDCheckMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09160B2261973B60014C3B9 /* IDCheckMessage.swift */; }; + A09160B6261973FA0014C3B9 /* PasswordEqualityMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09160B5261973FA0014C3B9 /* PasswordEqualityMessage.swift */; }; + A09160B9261974050014C3B9 /* UserNameCheckMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09160B8261974050014C3B9 /* UserNameCheckMessage.swift */; }; + A09B920D2617406000F6BC4A /* DelegationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09B920C2617406000F6BC4A /* DelegationProtocol.swift */; }; + A0A2C2F92612DDB800BBD554 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C2F82612DDB800BBD554 /* AppDelegate.swift */; }; + A0A2C2FB2612DDB800BBD554 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C2FA2612DDB800BBD554 /* SceneDelegate.swift */; }; + A0A2C2FD2612DDB800BBD554 /* SignUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C2FC2612DDB800BBD554 /* SignUpViewController.swift */; }; + A0A2C3002612DDB800BBD554 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A0A2C2FE2612DDB800BBD554 /* Main.storyboard */; }; + A0A2C3022612DDB900BBD554 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A0A2C3012612DDB900BBD554 /* Assets.xcassets */; }; + A0A2C3052612DDB900BBD554 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A0A2C3032612DDB900BBD554 /* LaunchScreen.storyboard */; }; + A0A2C3592612F2E300BBD554 /* StackViewUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C3582612F2E300BBD554 /* StackViewUnit.swift */; }; + A0A2C3602612FE3800BBD554 /* SignUpInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C35F2612FE3800BBD554 /* SignUpInfo.swift */; }; + A0A2C3632612FEBB00BBD554 /* SignUpViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A2C3622612FEBB00BBD554 /* SignUpViewModel.swift */; }; + A0A64573261AB9A8006EAC79 /* PasswordValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A64572261AB9A8006EAC79 /* PasswordValidation.swift */; }; + A0A64577261ABA1A006EAC79 /* NetworkingForIDCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A64576261ABA1A006EAC79 /* NetworkingForIDCheck.swift */; }; + A0A6457B261ABA38006EAC79 /* IDValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A6457A261ABA38006EAC79 /* IDValidation.swift */; }; + A0A6457F261ABF92006EAC79 /* PasswordEqualityValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A6457E261ABF92006EAC79 /* PasswordEqualityValidation.swift */; }; + A0A64582261AC24B006EAC79 /* UserNameValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0A64581261AC24B006EAC79 /* UserNameValidation.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + A01ADE9E2614541200C30356 /* IDTextFieldDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDTextFieldDelegate.swift; sourceTree = ""; }; + A01ADEA22614545E00C30356 /* PasswordTextFieldDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordTextFieldDelegate.swift; sourceTree = ""; }; + A01ADEA52614546C00C30356 /* CheckPasswordTextFieldDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPasswordTextFieldDelegate.swift; sourceTree = ""; }; + A01ADEA82614547900C30356 /* UserNameTextFieldDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNameTextFieldDelegate.swift; sourceTree = ""; }; + A07C89AA2618554F00DD3C4B /* PasswordCheckMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordCheckMessage.swift; sourceTree = ""; }; + A09160B2261973B60014C3B9 /* IDCheckMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDCheckMessage.swift; sourceTree = ""; }; + A09160B5261973FA0014C3B9 /* PasswordEqualityMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordEqualityMessage.swift; sourceTree = ""; }; + A09160B8261974050014C3B9 /* UserNameCheckMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNameCheckMessage.swift; sourceTree = ""; }; + A09B920C2617406000F6BC4A /* DelegationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DelegationProtocol.swift; sourceTree = ""; }; + A0A2C2F52612DDB800BBD554 /* SignUpApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SignUpApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A0A2C2F82612DDB800BBD554 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A0A2C2FA2612DDB800BBD554 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + A0A2C2FC2612DDB800BBD554 /* SignUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpViewController.swift; sourceTree = ""; }; + A0A2C2FF2612DDB800BBD554 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + A0A2C3012612DDB900BBD554 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A0A2C3042612DDB900BBD554 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + A0A2C3062612DDB900BBD554 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A0A2C3582612F2E300BBD554 /* StackViewUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackViewUnit.swift; sourceTree = ""; }; + A0A2C35F2612FE3800BBD554 /* SignUpInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpInfo.swift; sourceTree = ""; }; + A0A2C3622612FEBB00BBD554 /* SignUpViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpViewModel.swift; sourceTree = ""; }; + A0A64572261AB9A8006EAC79 /* PasswordValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordValidation.swift; sourceTree = ""; }; + A0A64576261ABA1A006EAC79 /* NetworkingForIDCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingForIDCheck.swift; sourceTree = ""; }; + A0A6457A261ABA38006EAC79 /* IDValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDValidation.swift; sourceTree = ""; }; + A0A6457E261ABF92006EAC79 /* PasswordEqualityValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordEqualityValidation.swift; sourceTree = ""; }; + A0A64581261AC24B006EAC79 /* UserNameValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNameValidation.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A0A2C2F22612DDB800BBD554 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A01ADE9D261453EF00C30356 /* SignUpTextFieldDelegate */ = { + isa = PBXGroup; + children = ( + A01ADE9E2614541200C30356 /* IDTextFieldDelegate.swift */, + A01ADEA22614545E00C30356 /* PasswordTextFieldDelegate.swift */, + A01ADEA52614546C00C30356 /* CheckPasswordTextFieldDelegate.swift */, + A01ADEA82614547900C30356 /* UserNameTextFieldDelegate.swift */, + ); + path = SignUpTextFieldDelegate; + sourceTree = ""; + }; + A09B920B2617404E00F6BC4A /* Protocol */ = { + isa = PBXGroup; + children = ( + A09B920C2617406000F6BC4A /* DelegationProtocol.swift */, + ); + path = Protocol; + sourceTree = ""; + }; + A0A2C2EC2612DDB800BBD554 = { + isa = PBXGroup; + children = ( + A0A2C2F72612DDB800BBD554 /* SignUpApp */, + A0A2C2F62612DDB800BBD554 /* Products */, + ); + sourceTree = ""; + }; + A0A2C2F62612DDB800BBD554 /* Products */ = { + isa = PBXGroup; + children = ( + A0A2C2F52612DDB800BBD554 /* SignUpApp.app */, + ); + name = Products; + sourceTree = ""; + }; + A0A2C2F72612DDB800BBD554 /* SignUpApp */ = { + isa = PBXGroup; + children = ( + A0A2C30D2612DF9800BBD554 /* SignUp */, + A0A2C2F82612DDB800BBD554 /* AppDelegate.swift */, + A0A2C2FA2612DDB800BBD554 /* SceneDelegate.swift */, + A0A2C2FE2612DDB800BBD554 /* Main.storyboard */, + A0A2C3012612DDB900BBD554 /* Assets.xcassets */, + A0A2C3032612DDB900BBD554 /* LaunchScreen.storyboard */, + A0A2C3062612DDB900BBD554 /* Info.plist */, + ); + path = SignUpApp; + sourceTree = ""; + }; + A0A2C30D2612DF9800BBD554 /* SignUp */ = { + isa = PBXGroup; + children = ( + A0A2C2FC2612DDB800BBD554 /* SignUpViewController.swift */, + A0A64575261ABA03006EAC79 /* Networking */, + A09B920B2617404E00F6BC4A /* Protocol */, + A01ADE9D261453EF00C30356 /* SignUpTextFieldDelegate */, + A0A2C3552612F29B00BBD554 /* SignUpModel */, + A0A2C3562612F2A700BBD554 /* SignUpView */, + A0A2C3572612F2AE00BBD554 /* SignUpViewModel */, + ); + path = SignUp; + sourceTree = ""; + }; + A0A2C3552612F29B00BBD554 /* SignUpModel */ = { + isa = PBXGroup; + children = ( + A0A2C35F2612FE3800BBD554 /* SignUpInfo.swift */, + ); + path = SignUpModel; + sourceTree = ""; + }; + A0A2C3562612F2A700BBD554 /* SignUpView */ = { + isa = PBXGroup; + children = ( + A0A2C3582612F2E300BBD554 /* StackViewUnit.swift */, + ); + path = SignUpView; + sourceTree = ""; + }; + A0A2C3572612F2AE00BBD554 /* SignUpViewModel */ = { + isa = PBXGroup; + children = ( + A0A2C3622612FEBB00BBD554 /* SignUpViewModel.swift */, + A0A64585261AF8F1006EAC79 /* Validation */, + A0A64584261AF8E6006EAC79 /* CheckMessage */, + ); + path = SignUpViewModel; + sourceTree = ""; + }; + A0A64575261ABA03006EAC79 /* Networking */ = { + isa = PBXGroup; + children = ( + A0A64576261ABA1A006EAC79 /* NetworkingForIDCheck.swift */, + ); + path = Networking; + sourceTree = ""; + }; + A0A64584261AF8E6006EAC79 /* CheckMessage */ = { + isa = PBXGroup; + children = ( + A09160B2261973B60014C3B9 /* IDCheckMessage.swift */, + A07C89AA2618554F00DD3C4B /* PasswordCheckMessage.swift */, + A09160B5261973FA0014C3B9 /* PasswordEqualityMessage.swift */, + A09160B8261974050014C3B9 /* UserNameCheckMessage.swift */, + ); + path = CheckMessage; + sourceTree = ""; + }; + A0A64585261AF8F1006EAC79 /* Validation */ = { + isa = PBXGroup; + children = ( + A0A6457A261ABA38006EAC79 /* IDValidation.swift */, + A0A64572261AB9A8006EAC79 /* PasswordValidation.swift */, + A0A6457E261ABF92006EAC79 /* PasswordEqualityValidation.swift */, + A0A64581261AC24B006EAC79 /* UserNameValidation.swift */, + ); + path = Validation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A0A2C2F42612DDB800BBD554 /* SignUpApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = A0A2C3092612DDB900BBD554 /* Build configuration list for PBXNativeTarget "SignUpApp" */; + buildPhases = ( + A0A2C2F12612DDB800BBD554 /* Sources */, + A0A2C2F22612DDB800BBD554 /* Frameworks */, + A0A2C2F32612DDB800BBD554 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SignUpApp; + productName = SignUpApp; + productReference = A0A2C2F52612DDB800BBD554 /* SignUpApp.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A0A2C2ED2612DDB800BBD554 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1240; + LastUpgradeCheck = 1240; + TargetAttributes = { + A0A2C2F42612DDB800BBD554 = { + CreatedOnToolsVersion = 12.4; + }; + }; + }; + buildConfigurationList = A0A2C2F02612DDB800BBD554 /* Build configuration list for PBXProject "SignUpApp" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A0A2C2EC2612DDB800BBD554; + productRefGroup = A0A2C2F62612DDB800BBD554 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A0A2C2F42612DDB800BBD554 /* SignUpApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A0A2C2F32612DDB800BBD554 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A0A2C3052612DDB900BBD554 /* LaunchScreen.storyboard in Resources */, + A0A2C3022612DDB900BBD554 /* Assets.xcassets in Resources */, + A0A2C3002612DDB800BBD554 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A0A2C2F12612DDB800BBD554 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A0A2C2FD2612DDB800BBD554 /* SignUpViewController.swift in Sources */, + A0A64573261AB9A8006EAC79 /* PasswordValidation.swift in Sources */, + A01ADEA32614545E00C30356 /* PasswordTextFieldDelegate.swift in Sources */, + A01ADEA62614546C00C30356 /* CheckPasswordTextFieldDelegate.swift in Sources */, + A0A2C2F92612DDB800BBD554 /* AppDelegate.swift in Sources */, + A0A64577261ABA1A006EAC79 /* NetworkingForIDCheck.swift in Sources */, + A01ADEA92614547900C30356 /* UserNameTextFieldDelegate.swift in Sources */, + A0A6457B261ABA38006EAC79 /* IDValidation.swift in Sources */, + A07C89AB2618554F00DD3C4B /* PasswordCheckMessage.swift in Sources */, + A0A2C2FB2612DDB800BBD554 /* SceneDelegate.swift in Sources */, + A0A64582261AC24B006EAC79 /* UserNameValidation.swift in Sources */, + A09160B3261973B60014C3B9 /* IDCheckMessage.swift in Sources */, + A09160B9261974050014C3B9 /* UserNameCheckMessage.swift in Sources */, + A0A2C3602612FE3800BBD554 /* SignUpInfo.swift in Sources */, + A01ADE9F2614541200C30356 /* IDTextFieldDelegate.swift in Sources */, + A0A2C3632612FEBB00BBD554 /* SignUpViewModel.swift in Sources */, + A09B920D2617406000F6BC4A /* DelegationProtocol.swift in Sources */, + A09160B6261973FA0014C3B9 /* PasswordEqualityMessage.swift in Sources */, + A0A2C3592612F2E300BBD554 /* StackViewUnit.swift in Sources */, + A0A6457F261ABF92006EAC79 /* PasswordEqualityValidation.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + A0A2C2FE2612DDB800BBD554 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A0A2C2FF2612DDB800BBD554 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + A0A2C3032612DDB900BBD554 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A0A2C3042612DDB900BBD554 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A0A2C3072612DDB900BBD554 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A0A2C3082612DDB900BBD554 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A0A2C30A2612DDB900BBD554 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = SignUpApp/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = asd.SignUpApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A0A2C30B2612DDB900BBD554 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = SignUpApp/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = asd.SignUpApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A0A2C2F02612DDB800BBD554 /* Build configuration list for PBXProject "SignUpApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A0A2C3072612DDB900BBD554 /* Debug */, + A0A2C3082612DDB900BBD554 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A0A2C3092612DDB900BBD554 /* Build configuration list for PBXNativeTarget "SignUpApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A0A2C30A2612DDB900BBD554 /* Debug */, + A0A2C30B2612DDB900BBD554 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A0A2C2ED2612DDB800BBD554 /* Project object */; +} diff --git a/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcuserdata/junhojang.xcuserdatad/UserInterfaceState.xcuserstate b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcuserdata/junhojang.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..2315495 Binary files /dev/null and b/SignUpApp/SignUpApp.xcodeproj/project.xcworkspace/xcuserdata/junhojang.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/SignUpApp/SignUpApp.xcodeproj/xcuserdata/junhojang.xcuserdatad/xcschemes/xcschememanagement.plist b/SignUpApp/SignUpApp.xcodeproj/xcuserdata/junhojang.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ec0fa1a --- /dev/null +++ b/SignUpApp/SignUpApp.xcodeproj/xcuserdata/junhojang.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + SignUpApp.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/SignUpApp/SignUpApp/AppDelegate.swift b/SignUpApp/SignUpApp/AppDelegate.swift new file mode 100644 index 0000000..6715b72 --- /dev/null +++ b/SignUpApp/SignUpApp/AppDelegate.swift @@ -0,0 +1,20 @@ +// +// AppDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + return true + } + +} + diff --git a/SignUpApp/SignUpApp/Assets.xcassets/AccentColor.colorset/Contents.json b/SignUpApp/SignUpApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/SignUpApp/SignUpApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SignUpApp/SignUpApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/SignUpApp/SignUpApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/SignUpApp/SignUpApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SignUpApp/SignUpApp/Assets.xcassets/Contents.json b/SignUpApp/SignUpApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/SignUpApp/SignUpApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SignUpApp/SignUpApp/Base.lproj/LaunchScreen.storyboard b/SignUpApp/SignUpApp/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/SignUpApp/SignUpApp/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SignUpApp/SignUpApp/Base.lproj/Main.storyboard b/SignUpApp/SignUpApp/Base.lproj/Main.storyboard new file mode 100644 index 0000000..84c15a5 --- /dev/null +++ b/SignUpApp/SignUpApp/Base.lproj/Main.storyboard @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SignUpApp/SignUpApp/Info.plist b/SignUpApp/SignUpApp/Info.plist new file mode 100644 index 0000000..5b531f7 --- /dev/null +++ b/SignUpApp/SignUpApp/Info.plist @@ -0,0 +1,66 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/SignUpApp/SignUpApp/SceneDelegate.swift b/SignUpApp/SignUpApp/SceneDelegate.swift new file mode 100644 index 0000000..85e8d17 --- /dev/null +++ b/SignUpApp/SignUpApp/SceneDelegate.swift @@ -0,0 +1,20 @@ +// +// SceneDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let _ = (scene as? UIWindowScene) else { return } + } + +} + diff --git a/SignUpApp/SignUpApp/SignUp/Networking/NetworkingForIDCheck.swift b/SignUpApp/SignUpApp/SignUp/Networking/NetworkingForIDCheck.swift new file mode 100644 index 0000000..09adfe6 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/Networking/NetworkingForIDCheck.swift @@ -0,0 +1,31 @@ +// +// NetworkingForIDCheck.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/05. +// + +import Foundation + +class NetworkingForIDCheck { + + static var idData = [String]() + + static func getData(completion: @escaping ([String]) -> ()) { + let URLString = "https://8r6ruzgzve.execute-api.ap-northeast-2.amazonaws.com/default/SwiftCamp" + if let url = URL(string: URLString) { + URLSession.shared.dataTask(with: url) { (data, response, error) in + if let data = data { + do { + let res = try JSONDecoder().decode([String].self, from: data) + idData = res + completion(res) + } catch let error { + print(error) + } + } + }.resume() + } + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/Protocol/DelegationProtocol.swift b/SignUpApp/SignUpApp/SignUp/Protocol/DelegationProtocol.swift new file mode 100644 index 0000000..c07d06c --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/Protocol/DelegationProtocol.swift @@ -0,0 +1,16 @@ +// +// DelegationProtocol.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/02. +// + +import Foundation + +protocol CheckDelegation { + func checkPassword() + func checkID() + func checkPasswordEquality() + func checkUserNameInput() + func buttonStateCondition() -> Bool +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpModel/SignUpInfo.swift b/SignUpApp/SignUpApp/SignUp/SignUpModel/SignUpInfo.swift new file mode 100644 index 0000000..0d8a2b8 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpModel/SignUpInfo.swift @@ -0,0 +1,22 @@ +// +// SignUpInfo.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import Foundation + +struct SignUpInfo { + + let title: String + let placeholder: String + let warning: String + + init(title: String, placeholder: String, warning: String) { + self.title = title + self.placeholder = placeholder + self.warning = warning + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/CheckPasswordTextFieldDelegate.swift b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/CheckPasswordTextFieldDelegate.swift new file mode 100644 index 0000000..92cc09f --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/CheckPasswordTextFieldDelegate.swift @@ -0,0 +1,31 @@ +// +// CheckPasswordTextFieldDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/31. +// + +import UIKit + +class CheckPasswordTextFieldDelegate: NSObject, UITextFieldDelegate { + + var delegatedObject: CheckDelegation? + + func textFieldDidBeginEditing(_ textField: UITextField) { + textField.layer.borderWidth = 1.0 + textField.layer.borderColor = UIColor.systemBlue.cgColor + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + textField.layer.borderColor = UIColor.black.cgColor + delegatedObject?.checkPasswordEquality() + delegatedObject?.buttonStateCondition() + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/IDTextFieldDelegate.swift b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/IDTextFieldDelegate.swift new file mode 100644 index 0000000..96ded29 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/IDTextFieldDelegate.swift @@ -0,0 +1,31 @@ +// +// IDTextFieldDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/31. +// + +import UIKit + +class IDTextFieldDelegate: NSObject, UITextFieldDelegate { + + var delegatedObject: CheckDelegation? + + func textFieldDidBeginEditing(_ textField: UITextField) { + textField.layer.borderWidth = 1.0 + textField.layer.borderColor = UIColor.systemBlue.cgColor + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + textField.layer.borderColor = UIColor.black.cgColor + delegatedObject?.checkID() + delegatedObject?.buttonStateCondition() + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/PasswordTextFieldDelegate.swift b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/PasswordTextFieldDelegate.swift new file mode 100644 index 0000000..a5fe881 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/PasswordTextFieldDelegate.swift @@ -0,0 +1,31 @@ +// +// PasswordTextFieldDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/31. +// + +import UIKit + +class PasswordTextFieldDelegate: NSObject, UITextFieldDelegate { + + var delegatedObject: CheckDelegation? + + func textFieldDidBeginEditing(_ textField: UITextField) { + textField.layer.borderWidth = 1.0 + textField.layer.borderColor = UIColor.systemBlue.cgColor + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + textField.layer.borderColor = UIColor.black.cgColor + delegatedObject?.checkPassword() + delegatedObject?.buttonStateCondition() + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/UserNameTextFieldDelegate.swift b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/UserNameTextFieldDelegate.swift new file mode 100644 index 0000000..3c93cfc --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpTextFieldDelegate/UserNameTextFieldDelegate.swift @@ -0,0 +1,31 @@ +// +// UserNameTextFieldDelegate.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/31. +// + +import UIKit + +class UserNameTextFieldDelegate: NSObject, UITextFieldDelegate { + + var delegatedObject: CheckDelegation? + + func textFieldDidBeginEditing(_ textField: UITextField) { + textField.layer.borderWidth = 1.0 + textField.layer.borderColor = UIColor.systemBlue.cgColor + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + textField.layer.borderColor = UIColor.black.cgColor + delegatedObject?.checkUserNameInput() + delegatedObject?.buttonStateCondition() + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpView/StackViewUnit.swift b/SignUpApp/SignUpApp/SignUp/SignUpView/StackViewUnit.swift new file mode 100644 index 0000000..204b161 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpView/StackViewUnit.swift @@ -0,0 +1,60 @@ +// +// StackViewUnit.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import UIKit + +class StackViewUnit: UIStackView { + + var title: UILabel! + var textField: UITextField! + var subLabel: UILabel! + + required init(coder: NSCoder) { + super.init(coder: coder) + configureTitleLabel() + configureTextField() + configureSubLabel() + } + + override init(frame: CGRect) { + super.init(frame: frame) + configureTitleLabel() + configureTextField() + configureSubLabel() + } + + private func configureTitleLabel() { + title = UILabel() + title.textAlignment = .left + title.textColor = .black + title.font = UIFont(name: "HelveticaNeue-Bold", size: 14) + self.addArrangedSubview(title) + } + + private func configureTextField() { + textField = UITextField() + textField.layer.cornerRadius = 0 + textField.addConstraint(textField.heightAnchor.constraint(equalToConstant: 38)) + textField.addConstraint(textField.widthAnchor.constraint(equalToConstant: 302)) + textField.borderStyle = .bezel + textField.keyboardType = .default + textField.returnKeyType = .next + + textField.attributedPlaceholder = NSAttributedString(string: "", attributes: [NSAttributedString.Key.foregroundColor: UIColor(red: 141, green: 141, blue: 141, alpha: 1)]) + self.addArrangedSubview(textField) + } + + private func configureSubLabel() { + subLabel = UILabel() + subLabel.textAlignment = .left + subLabel.textColor = .black + subLabel.font = UIFont(name: "HelveticaNeue", size: 12) + self.addArrangedSubview(subLabel) + } + +} + diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewController.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewController.swift new file mode 100644 index 0000000..9323bcd --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewController.swift @@ -0,0 +1,196 @@ +// +// ViewController.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import UIKit + +class SignUpViewController: UIViewController { + + @IBOutlet weak var mainTitle: UILabel! + + @IBOutlet weak var idStackView: StackViewUnit! + @IBOutlet weak var passwordStackView: StackViewUnit! + @IBOutlet weak var checkPasswordStackView: StackViewUnit! + @IBOutlet weak var userNameStackView: StackViewUnit! + + @IBOutlet weak var nextButton: UIButton! + + @IBAction func nextButtonForModal(_ sender: Any) { + if buttonStateCondition() == true { + nextButton.isEnabled = true + } else if buttonStateCondition() == false { + nextButton.isEnabled = false + } + } + + private var signUpViewModel = SignUpViewModel() + + private let idTextFieldDelegate = IDTextFieldDelegate() + private let passwordTextFieldDelegate = PasswordTextFieldDelegate() + private let checkPasswordTextFieldDelegate = CheckPasswordTextFieldDelegate() + private let userNameTextFieldDelegate = UserNameTextFieldDelegate() + + private let idValidation = IDValidation() + private let passwordValidation = PasswordValidation() + private let passwordEqualityValidation = PasswordEqualityValidation() + private let userNameValidation = UserNameValidation() + + override func viewDidLoad() { + super.viewDidLoad() + setUp() + } + + private func setUp() { + setMain() + setButton() + setDelegation() + applyIDStackViewValue() + applyPasswordStackViewValue() + applyCheckPasswordStackViewValue() + applyUserNameStackViewValue() + nextButton.isEnabled = false + } + + private func setDelegation() { + idTextFieldDelegate.delegatedObject = self + passwordTextFieldDelegate.delegatedObject = self + checkPasswordTextFieldDelegate.delegatedObject = self + userNameTextFieldDelegate.delegatedObject = self + } + + internal func buttonStateCondition() -> Bool { + if idStackView.subLabel.textColor == .systemGreen && passwordStackView.subLabel.textColor == .systemGreen && checkPasswordStackView.subLabel.textColor == .systemGreen && userNameStackView.subLabel.textColor == .systemGreen { + return true + } else { + return false + } + } + +} + +extension SignUpViewController: CheckDelegation { + + internal func checkID() { + if let userInput = idStackView.textField.text { + let message = idValidation.checkIDResult(input: userInput) + let isValid = idValidation.returnValidationResult(input: userInput) + if isValid == true { + idStackView.subLabel.textColor = .systemGreen + } else { + idStackView.textField.layer.borderColor = UIColor.systemRed.cgColor + idStackView.subLabel.textColor = .systemRed + } + idStackView.subLabel.text = message + } + } + + internal func checkPassword() { + checkPasswordEquality() + if let userInput = passwordStackView.textField.text { + let message = passwordValidation.checkPasswordResult(input: userInput) + let isValid = passwordValidation.returnValidationResult(input: userInput) + if isValid == true { + passwordStackView.subLabel.textColor = .systemGreen + } else { + passwordStackView.textField.layer.borderColor = UIColor.systemRed.cgColor + passwordStackView.subLabel.textColor = .systemRed + } + passwordStackView.subLabel.text = message + } + } + + internal func checkPasswordEquality() { + if let userInput = passwordStackView.textField.text, let userSecondInput = checkPasswordStackView.textField.text { + let message = passwordEqualityValidation.checkEqualityResult(input: userInput, secondInput: userSecondInput) + let isValid = passwordEqualityValidation.returnValidationResult(input: userInput, secondInput: userSecondInput) + if isValid == true { + checkPasswordStackView.subLabel.textColor = .systemGreen + } else { + checkPasswordStackView.textField.layer.borderColor = UIColor.systemRed.cgColor + checkPasswordStackView.subLabel.textColor = .systemRed + } + checkPasswordStackView.subLabel.text = message + } + } + + internal func checkUserNameInput() { + if let userInput = userNameStackView.textField.text { + let message = userNameValidation.checkUserNameResult(input: userInput) + let isValid = userNameValidation.returnValidationResult(input: userInput) + if isValid == true { + userNameStackView.subLabel.textColor = .systemGreen + } else { + userNameStackView.textField.layer.borderColor = UIColor.systemRed.cgColor + userNameStackView.subLabel.textColor = .systemRed + } + userNameStackView.subLabel.text = message + } + } + +} + +extension SignUpViewController { + + private func setMain() { + self.view.backgroundColor = UIColor(red: 245, green: 246, blue: 247, alpha: 1) + mainTitle.textAlignment = .center + mainTitle.text = signUpViewModel.mainTitle + mainTitle.textColor = .systemGreen + mainTitle.font = UIFont(name: "HelveticaNeue-Bold", size: 30) + } + + private func setButton() { + let buttonImage = UIImage(systemName: "chevron.forward.circle.fill") + nextButton.layer.borderColor = UIColor.black.cgColor + nextButton.layer.borderWidth = 1 + nextButton.setImage(buttonImage, for: .normal) + nextButton.setTitle("다음", for: .normal) + nextButton.tintColor = UIColor.systemGreen + } + + private func applyIDStackViewValue() { + let signUpIDContent = signUpViewModel.idContent + idStackView.title.text = signUpIDContent.title + idStackView.textField.delegate = idTextFieldDelegate + idStackView.textField.placeholder = signUpIDContent.placeholder + idStackView.textField.font = UIFont.init(name: ("HelveticaNeue"), size: 14) + idStackView.subLabel.text = signUpViewModel.emptyString + self.view.addSubview(idStackView) + } + + private func applyPasswordStackViewValue() { + let signUpPasswordContent = signUpViewModel.passwordContent + passwordStackView.title.text = signUpPasswordContent.title + passwordStackView.textField.delegate = passwordTextFieldDelegate + passwordStackView.textField.isSecureTextEntry = true + passwordStackView.textField.placeholder = signUpPasswordContent.placeholder + passwordStackView.textField.font = UIFont.init(name: ("HelveticaNeue"), size: 14) + passwordStackView.subLabel.text = signUpViewModel.emptyString + self.view.addSubview(passwordStackView) + } + + private func applyCheckPasswordStackViewValue() { + let signUpCheckPasswordContent = signUpViewModel.checkPasswordContent + checkPasswordStackView.title.text = signUpCheckPasswordContent.title + checkPasswordStackView.textField.delegate = checkPasswordTextFieldDelegate + checkPasswordStackView.textField.isSecureTextEntry = true + checkPasswordStackView.textField.placeholder = signUpCheckPasswordContent.placeholder + checkPasswordStackView.textField.font = UIFont.init(name: ("HelveticaNeue"), size: 14) + checkPasswordStackView.subLabel.text = signUpViewModel.emptyString + self.view.addSubview(checkPasswordStackView) + } + + private func applyUserNameStackViewValue() { + let signUpUserNameContent = signUpViewModel.userNameContent + userNameStackView.title.text = signUpUserNameContent.title + userNameStackView.textField.delegate = userNameTextFieldDelegate + userNameStackView.textField.placeholder = signUpUserNameContent.placeholder + userNameStackView.textField.font = UIFont.init(name: ("HelveticaNeue"), size: 14) + userNameStackView.subLabel.text = signUpViewModel.emptyString + self.view.addSubview(userNameStackView) + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/IDCheckMessage.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/IDCheckMessage.swift new file mode 100644 index 0000000..aeef6e1 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/IDCheckMessage.swift @@ -0,0 +1,14 @@ +// +// IDCheckMessage.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/04. +// + +import Foundation + +enum IDCheckMessage: String { + case usedIDWarning = "이미 사용중인 아이디입니다." + case charcterWarning = "5~20자의 영문 소문자, 숫자와 특수기호(_)(-)만 사용 가능합니다." + case validatedCaseMessage = "사용 가능한 아이디입니다." +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordCheckMessage.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordCheckMessage.swift new file mode 100644 index 0000000..a4e48cf --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordCheckMessage.swift @@ -0,0 +1,16 @@ +// +// PasswordCheckMessage.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/03. +// + +import Foundation + +enum PasswordCheckMessage: String { + case characterNumberWarning = "8자 이상 16자 이하로 입력해주세요." + case charcterUpperWarning = "영문 대문자를 최소 1자 이상 포함해주세요." + case numberIncludedWarning = "숫자를 최소 1자 이상 포함해주세요." + case specialCharacterWarning = "특수문자를 최소 1자 이상 포함해주세요." + case validatedCaseMessage = "안전한 비밀번호입니다." +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordEqualityMessage.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordEqualityMessage.swift new file mode 100644 index 0000000..94cd600 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/PasswordEqualityMessage.swift @@ -0,0 +1,13 @@ +// +// PasswordEqualityMessage.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/04. +// + +import Foundation + +enum PasswordEqualityMessage: String { + case notEqualPasswordWarning = "비밀번호가 일치하지 않습니다." + case validatedCaseMessage = "비밀번호가 일치합니다." +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/UserNameCheckMessage.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/UserNameCheckMessage.swift new file mode 100644 index 0000000..448144e --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/CheckMessage/UserNameCheckMessage.swift @@ -0,0 +1,13 @@ +// +// UserNameCheckMessage.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/04. +// + +import Foundation + +enum UserNameCheckMessage: String { + case notInputWarning = "이름은 필수 입력 항목입니다." + case validatedCaseMessage = " " +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/SignUpViewModel.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/SignUpViewModel.swift new file mode 100644 index 0000000..8908075 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/SignUpViewModel.swift @@ -0,0 +1,20 @@ +// +// SignUpViewModel.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/03/30. +// + +import Foundation + +class SignUpViewModel { + + let mainTitle = "회원가입" + let emptyString = " " + + let idContent: SignUpInfo = SignUpInfo(title: "아이디", placeholder: "영문 소문자, 숫자, 특수기호(_, -), 5~20자", warning: "이미 사용중인 아이디입니다.") + let passwordContent: SignUpInfo = SignUpInfo(title: "비밀번호", placeholder: "영문 대/소문자, 숫자, 특수문자(!@#$%) 8~16자", warning: "안전한 비밀번호입니다.") + let checkPasswordContent: SignUpInfo = SignUpInfo(title: "비밀번호 재확인", placeholder: "", warning: "비밀번호가 일치하지 않습니다.") + let userNameContent: SignUpInfo = SignUpInfo(title: "이름", placeholder: "", warning: "이름은 필수 입력 항목입니다.") + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/IDValidation.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/IDValidation.swift new file mode 100644 index 0000000..8c9dc0b --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/IDValidation.swift @@ -0,0 +1,60 @@ +// +// IDValidation.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/05. +// + +import Foundation + +class IDValidation { + + private var idList = [String]() + + init() { + NetworkingForIDCheck.getData { serverIdList in + self.idList = serverIdList + } + } + + private func returnValidation(input: String) -> Bool { + if isValidCharacterID(input: input) == true && isUnique(input: input) == true { + return true + } else { + return false + } + } + + private func checkID(input: String) -> String { + if isUnique(input: input) == false { + return IDCheckMessage.usedIDWarning.rawValue + } else if isValidCharacterID(input: input) == false { + return IDCheckMessage.charcterWarning.rawValue + } else { + return IDCheckMessage.validatedCaseMessage.rawValue + } + } + + private func isValidCharacterID(input: String) -> Bool { + let passwordRegEx = "^(?=.*[a-z0-9_-]).{5,20}" + let passwordTest = NSPredicate(format: "SELF MATCHES %@", passwordRegEx) + return passwordTest.evaluate(with: input) + } + + private func isUnique(input: String) -> Bool { + if idList.contains(input) { + return false + } else { + return true + } + } + + func returnValidationResult(input: String) -> Bool { + return returnValidation(input: input) + } + + func checkIDResult(input: String) -> String { + return checkID(input: input) + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordEqualityValidation.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordEqualityValidation.swift new file mode 100644 index 0000000..060e3e7 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordEqualityValidation.swift @@ -0,0 +1,44 @@ +// +// PasswordEqualityValidation.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/05. +// + +import Foundation + +class PasswordEqualityValidation { + + private func returnValidation(input: String, secondInput: String) -> Bool { + if isEqual(input: input, secondInput: secondInput) == true { + return true + } else { + return false + } + } + + private func checkEquality(input: String, secondInput: String) -> String { + if isEqual(input: input, secondInput: secondInput) == false { + return PasswordEqualityMessage.notEqualPasswordWarning.rawValue + } else { + return PasswordEqualityMessage.validatedCaseMessage.rawValue + } + } + + private func isEqual(input: String, secondInput: String) -> Bool { + if input != secondInput { + return false + } else { + return true + } + } + + func returnValidationResult(input: String, secondInput: String) -> Bool { + return returnValidation(input: input, secondInput: secondInput) + } + + func checkEqualityResult(input: String, secondInput: String) -> String { + return checkEquality(input: input, secondInput: secondInput) + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordValidation.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordValidation.swift new file mode 100644 index 0000000..1837e5d --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/PasswordValidation.swift @@ -0,0 +1,67 @@ +// +// PasswordValidation.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/05. +// + +import Foundation + +class PasswordValidation { + + private func returnValidation(input: String) -> Bool { + if isCharNumValid(input: input) == true && isUpperCharacterIncludedPassword(input: input) == true && isNumberIncludedPassword(input: input) == true && isSpecialCharacterIncludedPassword(input: input) == true { + return true + } else { + return false + } + } + + private func checkPassword(input: String) -> String { + if isCharNumValid(input: input) == false { + return PasswordCheckMessage.characterNumberWarning.rawValue + } else if isUpperCharacterIncludedPassword(input: input) == false { + return PasswordCheckMessage.charcterUpperWarning.rawValue + } else if isNumberIncludedPassword(input: input) == false { + return PasswordCheckMessage.numberIncludedWarning.rawValue + } else if isSpecialCharacterIncludedPassword(input: input) == false { + return PasswordCheckMessage.specialCharacterWarning.rawValue + } + return PasswordCheckMessage.validatedCaseMessage.rawValue + } + + private func isCharNumValid(input: String) -> Bool { + if input.count > 16 || input.count < 8 { + return false + } else { + return true + } + } + + private func isUpperCharacterIncludedPassword(input: String) -> Bool { + let passwordRegEx = "^(?=.*[A-Z]).{8,16}" + let passwordTest = NSPredicate(format: "SELF MATCHES %@", passwordRegEx) + return passwordTest.evaluate(with: input) + } + + private func isNumberIncludedPassword(input: String) -> Bool { + let passwordRegEx = "^(?=.*[0-9]).{8,16}" + let passwordTest = NSPredicate(format: "SELF MATCHES %@", passwordRegEx) + return passwordTest.evaluate(with: input) + } + + private func isSpecialCharacterIncludedPassword(input: String) -> Bool { + let passwordRegEx = "^(?=.*[!@#$%]).{8,16}" + let passwordTest = NSPredicate(format: "SELF MATCHES %@", passwordRegEx) + return passwordTest.evaluate(with: input) + } + + func returnValidationResult(input: String) -> Bool { + return returnValidation(input: input) + } + + func checkPasswordResult(input: String) -> String { + return checkPassword(input: input) + } + +} diff --git a/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/UserNameValidation.swift b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/UserNameValidation.swift new file mode 100644 index 0000000..379b715 --- /dev/null +++ b/SignUpApp/SignUpApp/SignUp/SignUpViewModel/Validation/UserNameValidation.swift @@ -0,0 +1,44 @@ +// +// UserNameValidation.swift +// SignUpApp +// +// Created by Jun Ho JANG on 2021/04/05. +// + +import Foundation + +class UserNameValidation { + + private func returnValidation(input: String) -> Bool { + if isInput(input: input) == true { + return true + } else { + return false + } + } + + private func checkUserNameInput(input: String) -> String { + if isInput(input: input) == false { + return UserNameCheckMessage.notInputWarning.rawValue + } else { + return UserNameCheckMessage.validatedCaseMessage.rawValue + } + } + + private func isInput(input: String) -> Bool { + if input.isEmpty { + return false + } else { + return true + } + } + + func returnValidationResult(input: String) -> Bool { + return returnValidation(input: input) + } + + func checkUserNameResult(input: String) -> String { + return checkUserNameInput(input: input) + } + +}