[Clone App] Login - SwiftUI (#1)

2023. 7. 6. 16:49iOS 개발/SwiftUI

스터디에서 SwiftUI로그인 화면을 만들어 보기로 했다!

데이터가 저장되고 실제 로그인되는건 아니지만 로그인화면의 다양한 기능을 구현해야 한다.

 

 

우선 화면 구성은 위 사진과 같다.

먼저 1주차에선 화면 구성, 이메일 정규식, 비밀번호 텍스트 필드, 로그인 동의를 구현하기로 했다.

 

화면구성 

1. Log in (navigationTitle) : NavigationStack 이나 NavigationView를 써서 안쪽 view에 .navigationTitle("Log in")을 주면된다.

struct ContentView: View {

 var body: some View {
        NavigationView {
            VStack {
            
            }.navigationTitle("Log in")
        }
  }      
}

 

2. Description text (Text) : 위 코드 VStack안에 Text("Introduce your credentials" )써주면 된다.

 Text("Introduce your credentials")

 

3. Email textField (TextField) : TextField() 안에 비었을 때 보여질값 , 바인딩 될 text 값을 넣으면 된다.

@State private var userID: String = "" //@State로 TextField의 text값이 바뀔때마다 값이 바뀜
									   
TextField("ID" , text: $userID)
        .fontWeight(.bold) //글씨체 두껍게
     	.padding() //주변 뷰들과 간격 벌리기
        .foregroundColor(.black) //글씨색깔 검정색
        .frame(maxWidth: .infinity) //폭넓이 최대
        .background(.bar) //배경색
        .cornerRadius(10) //모서리 둥글게
        .keyboardType(.emailAddress) //이메일 형식의 키보드 올라오게

 

4. Password secured textField (SecureField) : 입력되는 값이 가려지기 위해 SecureField를 쓴다. TextField와 마찬가지로 비었을 때 보여질값 , 바인딩 될 text 값을 넣으면 된다.

@State private var userPassword: String = "" //@State로 SecureField의 text값이 바뀔때마다 값이 바뀜
  
SecureField("PASSWORD" , text: $userPassword)
        .fontWeight(.bold) //글씨체
        .padding() //버튼과의 간격
        .foregroundColor(.black) //글씨색깔
        .frame(maxWidth: .infinity) //폭넓이 최대
        .background(.bar) //배경색
        .cornerRadius(10) //모서리 둥글게

 

5. Toggle (Toggle) : Toggle도 작동하려면 TextField와 마찬가지로 바인딩 될 Bool값이 필요하다. isOn에 바인딩 값을 넣어주면 된다. Bool값이 false면 닫히고 true면 열린다.

@State private var loginAgree: Bool = false //@State로 Toggle의 값이 바뀔때마다 값이 바뀜
HStack {
        Text("Agree to terms and conditions").font(.caption2)
        Toggle(isOn: $loginAgree) {
                            
        }
}

 

6. Sign in Button (Button) : 로그인 버튼이고 action과 label로 구현한다. action에는 버튼을 눌렀을때 이벤트 , label에는 버튼 UI를 나타낸다. 버튼을 눌렀을때 이메일 정규식이 맞고 로그인 동의가 되어야만 로그인 성공 메시지가 뜬다.

@State private var message: String = "" //로그인 여부에 따라 보여질 메시지 값
@State private var isValidEmail: Bool = false  //이메일 형식 여부 값

Button {
        checkLogin() //로그인 함수                       
} label: {
        Text("Sign in")
        .fontWeight(.bold) //글씨체
        .foregroundColor(.white) //글씨색깔
        .frame(width : 300) //폭넓이
        .padding() //주변뷰들과 간격 넓힘
        .background(.blue) //배경 : 파랑색
        .cornerRadius(10) //모서리 둥글게
}

//이메일 정규표현식 확인하기 위한 함수
 func isValidEmailAddress(_ email: String) -> Bool { 
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        //일반적인 이메일 주소 패턴
        
        let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex) 
        //NSPredicate를 이용하여 주어진 문자열이 자기 자신과 정규식 패턴과 일치하는지를 평가
        
        return emailPredicate.evaluate(with: email)
        //입력한 이메일이 위의 정규식과 일치 불일치를 Bool값
}

//로그인 함수
func checkLogin() {
        isValidEmail = isValidEmailAddress(userID) 
        //userID를 위 함수에 보내서 이메일 정규식이 맞는지 확인 맞으면 true , 틀리면 false
        
        if loginAgree == false { //로그인 동의 토글값이 false이면 
            message = "로그인 동의를 해주세요"
        } else if isValidEmail == false { //이메일 형식이 false이면
            message = "이메일 형식이 아닙니다"
        } else {
            message = "아이디 : \(userID) 비밀번호 : \(userPassword)"
        }
}

 

 

구현영상

 

 

전체코드

struct ContentView: View {
    @State private var userID: String = ""
    @State private var userPassword: String = ""
    @State private var loginAgree: Bool = false
    @State private var message: String = ""
    @State private var isValidEmail: Bool = false
    var body: some View {
        NavigationView {
                   VStack {
                       Text("Introduce your credentials")
                       TextField("ID" , text: $userID)
                               .fontWeight(.bold) //글씨체 두껍게
                               .padding() //주변 뷰들과 간격 벌리기
                               .foregroundColor(.black) //글씨색깔 검정색
                               .frame(maxWidth: .infinity) //폭넓이 최대
                               .background(.bar) //배경색
                               .cornerRadius(10) //모서리 둥글게
                               .keyboardType(.emailAddress) //이메일 형식의 키보드 올라오게
                       
                       SecureField("PASSWORD" , text: $userPassword)
                               .fontWeight(.bold) //글씨체
                               .padding() //버튼과의 간격
                               .foregroundColor(.black) //글씨색깔
                               .frame(maxWidth: .infinity) //폭넓이 최대
                               .background(.bar) //배경색
                               .cornerRadius(10) //모서리 둥글게
                       
                       Spacer().frame(height : 30)
                       
                       HStack {
                               Text("Agree to terms and conditions").font(.caption2)
                               Toggle(isOn: $loginAgree) {
                                                   
                               }
                       }
                       
                       Spacer().frame(height : 30)
                       Button {
                               checkLogin() //로그인 함수
                       } label: {
                               Text("Sign in")
                               .fontWeight(.bold) //글씨체
                               .foregroundColor(.white) //글씨색깔
                               .frame(width : 300) //폭넓이
                               .padding() //주변뷰들과 간격 넓힘
                               .background(.blue) //배경 : 파랑색
                               .cornerRadius(10) //모서리 둥글게
                       }
                       
                       Spacer().frame(height : 30)
                       Text("\(message)")
                       Spacer()
                   }.navigationTitle("Log in").padding()
               }
    }
    
    //이메일 정규표현식 확인하기 위한 함수
     func isValidEmailAddress(_ email: String) -> Bool {
            let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
            //일반적인 이메일 주소 패턴
            
            let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex)
            //NSPredicate를 이용하여 주어진 문자열이 자기 자신과 정규식 패턴과 일치하는지를 평가
            
            return emailPredicate.evaluate(with: email)
            //입력한 이메일이 위의 정규식과 일치 불일치를 Bool값
    }

    //로그인 함수
    func checkLogin() {
            isValidEmail = isValidEmailAddress(userID)
            //userID를 위 함수에 보내서 이메일 정규식이 맞는지 확인 맞으면 true , 틀리면 false
            
            if loginAgree == false { //로그인 동의 토글값이 false이면
                message = "로그인 동의를 해주세요"
            } else if isValidEmail == false { //이메일 형식이 false이면
                message = "이메일 형식이 아닙니다"
            } else {
                message = "아이디 : \(userID) \n비밀번호 : \(userPassword)"
            }
    }
}