IOS(Swift)

[IOS/Swift] μ½˜ν…μΈ  검색 μ•± κ΅¬ν˜„ - 3. νšŒμ›κ°€μž… UI κ΅¬ν˜„

Tempo 2022. 4. 4. 21:39

Swift UI λ₯Ό μ‚¬μš©ν•œ νšŒμ›κ°€μž… 및 둜그인 ν™”λ©΄ κ΅¬ν˜„ - λ°±μ—”λ“œλŠ” Django RestFramework μ‚¬μš©

κ΅¬ν˜„ μ˜ˆμ‹œ - νšŒμ›κ°€μž…

νšŒμ› κ°€μž…μ€ 4개 ν•­λͺ© (λ‹‰λ„€μž„, 이메일, λΉ„λ°€λ²ˆν˜Έ(+λΉ„λ°€λ²ˆν˜Έ 확인), MBTI ν•­λͺ©)을 μž…λ ₯λ°›λŠ” 화면을 λ§Œλ“ λ‹€. μ—¬κΈ°μ„œ MBTI ν•­λͺ©μ€ HTMLμ—μ„œ λ§ν•˜λŠ” μ…€λ ‰νŠΈ λ°•μŠ€ UIλ₯Ό μ‚¬μš©ν•˜μ—¬ MBTIλ₯Ό μ„ νƒν•˜λ„λ‘ ν•˜μ˜€λ‹€.

//
//  SignUpView.swift
//  mbtiPlayground
//
//  Created by λ°•μ’…ν›„ on 2022/03/16.
//

import SwiftUI

struct SignUpView: View {
    @Environment(\\.presentationMode) var presentationMode: Binding<PresentationMode>
    @State private var showingAlert = false
    @State var uiTabarController: UITabBarController?
    
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var rePassword: String = ""
    @State private var username: String = ""
    @State private var mbti = 0
    let mbtiPicker = ["ISTJ", "ISFJ", "INFJ", "INTJ", "ISTP", "ISFP", "INFP","INTP", "ESTP", "ESFP", "ENFP", "ENTP", "ESTJ", "ESFJ", "ENFJ", "ENTJ"]
    
    var btnBack : some View { Button(action: {
        self.showingAlert = true
    }){
        Text("λ’€λ‘œκ°€κΈ°")
    }.alert(isPresented: $showingAlert){
        Alert(title: Text("νšŒμ› κ°€μž… μ·¨μ†Œ"), message: Text("νšŒμ›κ°€μž…μ„ μ·¨μ†Œν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?"),
              primaryButton: .destructive(Text("μ·¨μ†Œν•˜κΈ°"), action: {
            presentationMode.wrappedValue.dismiss()
        })
              , secondaryButton: .cancel(Text("μ΄μ–΄ν•˜κΈ°")))
    }
        
    }
    
    var body: some View {
        VStack{
            Text("Sign Up")
                .font(.title)
                .fontWeight(.medium)
                .padding()
                .foregroundColor(.black)
                .frame(width: 300)
            
            HStack{
                Image(systemName: "tag")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 30, height: 30)
                    .padding(.bottom)
                
                TextField("λ‹‰λ„€μž„μ„ μž…λ ₯ν•˜μ„Έμš”", text: $username)
                    .frame(width: 300, height: 10)
                    .padding()
                    .background(Color(.systemGray6))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
                    
            }
            HStack{
                Image(systemName: "person.fill")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 30, height: 30)
                    .padding(.bottom)
                
                TextField("이메일을 μž…λ ₯ν•˜μ„Έμš”.", text: $email)
                    .frame(width: 300, height: 10)
                    .padding()
                    .background(Color(.systemGray6))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
                    
            }
            HStack{
                Image(systemName: "lock")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 30, height: 30)
                    .padding(.bottom)
                    
                SecureField("λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜μ„Έμš”", text: $password)
                    .frame(width: 300, height: 10)
                    .padding()
                    .background(Color(.systemGray6))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
            }
            HStack{
                Image(systemName: "lock.rotation")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 30, height: 30)
                    .padding(.bottom)
                    
                SecureField("λΉ„λ°€λ²ˆν˜Έλ₯Ό λ‹€μ‹œ μž…λ ₯ν•˜μ„Έμš”", text: $rePassword)
                    .frame(width: 300, height: 10)
                    .padding()
                    .background(Color(.systemGray6))
                    .cornerRadius(5.0)
                    .padding(.bottom, 20)
            }
            HStack{
                Text("MBTI μœ ν˜•μ„ μ„ νƒν•˜μ„Έμš”: ")
                    .font(.headline)
                    .fontWeight(.medium)
                    .padding()
                Picker("MBTI μœ ν˜•μ„ μ„ νƒν•˜μ„Έμš”", selection: $mbti){
                    ForEach(0 ..< mbtiPicker.count){
                        Text(self.mbtiPicker[$0])
                    }
                }
            }
            
            
            Button(action: {
                print(self.email + self.password + self.rePassword + String(self.mbtiPicker[self.mbti])+self.username)
                
                sendPostRequest("<http://localhost:8000/auth/signup>", parameters:
                                ["email": self.email, "username": self.username, "password": self.password, "mbti": self.mbtiPicker[self.mbti]]
                                 ){
                    responseObject, error in guard let _ = responseObject, error == nil else {
                        print(error ?? "Unknown error")
                        return
                    }
                }
                self.presentationMode.wrappedValue.dismiss()
            }){
                Text("νšŒμ›κ°€μž…")
                    .frame(width: 80, height: 10)
                    .font(.headline)
                    .foregroundColor(.white)
                    .padding()
                    .background(Color(.systemBlue))
                    .cornerRadius(10)
                    
            }
            .padding()
            .onSubmit {
                
            }
        }
        .padding(.all, 30)
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: btnBack)
    }
}

struct SignUpView_Previews: PreviewProvider {
    static var previews: some View {
        SignUpView()
    }
}

νšŒμ› κ°€μž… μ‹œ Post μš”μ²­μœΌλ‘œ λ³΄λ‚΄λŠ” ν•¨μˆ˜λŠ” μ•„λž˜μ™€ κ°™λ‹€ sendPostRequest

import Foundation

func sendPostRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
    let targetUrl = URL(string: url)
    let paramData = try? JSONSerialization.data(withJSONObject: parameters)
    
    var request = URLRequest(url: targetUrl!)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = paramData
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard
            let data = data,                              // is there data
            let response = response as? HTTPURLResponse,  // is there HTTP response
            200 ..< 300 ~= response.statusCode,           // is statusCode 2XX
            error == nil                                  // was there no error
        else {
            completion(nil, error)
            return
        }
        
        let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
        completion(responseObject, nil)
    }
    task.resume()
}

그런데 μœ„ ν•¨μˆ˜λ₯Ό 보면 Pyhon κ³ΌλŠ” λ‹€λ₯΄κ²Œ Return 값이 μ—†λ‹€.

이 μ½”λ“œμ— λŒ€ν•΄ μ„€λͺ…ν•˜μžλ©΄ URLSession μ•ˆμ— 미리 μš”μ²­ λ‚΄μš©μ„ λ‹΄μ•„λ‘” ν›„ 호좜, μ‹€μ œ μ‹€ν–‰(task.resume()) λΆ€λΆ„μ—μ„œ ν˜ΈμΆœν•˜μ—¬ 받은 λ‚΄μš©μ„ κ°€μ Έμ˜¨λ‹€.

κ·Έλ ‡λ‹€λ³΄λ‹ˆ 처음 swift λ₯Ό μ ‘ν•œ λ‚˜μ—κ²ŒλŠ” μ–΄λ–»κ²Œ API 응닡 μ½”λ“œμ— λŒ€ν•΄ μ²˜λ¦¬ν•˜λŠ”μ§€ μ˜λ¬Έμ΄μ—ˆλ‹€.

κ·Έλž˜μ„œ 보톡 μ‚¬μš©μ€ μ•„λž˜μ²˜λŸΌ μ‚¬μš©ν•˜κ²Œ λœλ‹€.

sendPostRequest("<http://localhost:8000/auth/signup>", parameters:
                                ["email": self.email, "username": self.username, "password": self.password, "mbti": self.mbtiPicker[self.mbti]]
                                 ){
                    responseObject, error in guard let _ = responseObject, error == nil else {
                        print(error ?? "Unknown error")
                        return
                    }
                }
                self.presentationMode.wrappedValue.dismiss()

μœ„ μ½”λ“œλŠ” UI μ½”λ“œ λ‚΄μ—μ„œ νšŒμ›κ°€μž… λ²„νŠΌ 클릭 μ‹œ μ•‘μ…˜μ—μ„œ λ™μž‘ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€. Swift μ—μ„œλŠ” ν•¨μˆ˜μ˜ return 값을 클래슀의 λ³€μˆ˜λ‘œ ν• λ‹Ήν•˜λŠ” 뢀뢄이 μžˆλŠ” 것이 μ•„λ‹Œ, μš”μ²­ ν•¨μˆ˜ λ‚΄μ—μ„œ self.XXX λ‘œ 클래슀 λ³€μˆ˜μ— μ ‘κ·Όν•˜μ—¬ 값을 λ³€κ²½ν•˜λŠ”κ²Œ λŒ€λΆ€λΆ„μ΄λ‹€.

μ΄λ ‡λ‹€λ³΄λ‹ˆ Swift UI λ‚΄μ—μ„œ 클래슀 λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  잘 μ‚¬μš©ν•˜λŠ” 방법을 μ—°κ΅¬ν•˜μ—¬μ•Ό ν•œλ‹€.

λ°˜μ‘ν˜•