개발 못해요! 그냥 못해요

[iOS/Swift] 프로젝트 생성 | 화면 전환 | 데이터 전달 (당근 클론 코딩) 본문

Study/iOS

[iOS/Swift] 프로젝트 생성 | 화면 전환 | 데이터 전달 (당근 클론 코딩)

this_is_mins 2024. 3. 31. 18:44

프로젝트 생성하기

 

 

폰트 사용하기

font 폴더를 만들어준당

원하는 폰트를 다운 받아 만들어준 폴더에 넣어준다(pretedard를 사용했다)

info.plist에서 Fonts proided by application을 추가로 생성해주고 아이템을 추가한다

{폰트명.확장자}까지 작성해준다

 

폰트 설정 끝~~

 

UIComponent (Login 화면 만들기)

LoginViewController 생성

- UIKit 임포트하기

import Foundation
import UIKit

class LoginViewController: UIViewController{
    
    
}

 

//
//  LoginViewController.swift
//  34th-Sopt-Seminar
//
//  Created by 김민서 on 2024/03/31.
//

import Foundation
import UIKit

class LoginViewController: UIViewController{
    //UILabel
    
    //타이틀 텍스트
    private let titleLabel: UILabel = {
        let label = UILabel (frame: CGRect(x:69,y:161,width:236,height:44))
        label.text = "동네라서 가능한 모든 것\n 당근에서 가까운 이웃과 함께해요."
        label.textColor = .black
        label.textAlignment = .center
        label.numberOfLines = 2
        label.font = UIFont(name:"Pretendard-Bold",size: 18)
        
        return label
    }()
    
    //아이디 입력창
    private let idTextField: UITextField = {
        let textField = UITextField(frame: CGRect(x: 20, y: 276, width: 335, height: 52))
        textField.placeholder = "아이디"
        textField.font = UIFont(name:"Pretendard-Medium",size:14)
        textField.backgroundColor = UIColor(red: 221/255, green: 222/255, blue: 227/255, alpha: 1)
        textField.layer.cornerRadius = 3
        //padding
        let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 23, height: textField.frame.height))
            textField.leftView = paddingView
            textField.leftViewMode = .always
        return textField
    }()
    
    //비밀번호 입력창
    private let passwordTextField: UITextField = {
        let textField = UITextField(frame: CGRect(x: 20, y: 335, width: 335, height: 52))
        textField.placeholder = "비밀번호"
        textField.font = UIFont(name:"Pretendard-Medium",size:14)
        textField.backgroundColor = UIColor(red: 221/255, green: 222/255, blue: 227/255, alpha: 1)
        textField.layer.cornerRadius = 3
        let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 23, height: textField.frame.height))
            textField.leftView = paddingView
            textField.leftViewMode = .always
        return textField
    }()
    
    //로그인 버튼
    private lazy var loginButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 21, y: 422, width: 332, height: 58))
        button.backgroundColor = UIColor(red: 255/255, green: 111/255, blue: 15/255, alpha: 1)
        button.setTitle("로그인하기", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont(name:"Pretendard-Bold",size:18)
        button.layer.cornerRadius = 6
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.backgroundColor = .white
        [titleLabel,idTextField,passwordTextField,loginButton].forEach{
            self.view.addSubview($0)
        }
        
    }
}

 

imageView (WelcomeViewController)

assets 폴더를 생성해 사용할 이미지 파일을 넣어준다

 

private let imageView : UIImageView = {
        let imageView = UIImageView(frame: CGRect(x: 112, y: 87, width: 150, height: 150))
        imageView.image = UIImage(named:"puppy.png")
        
        return imageView
}()

다른 컴포넌트와 마찬가지로 크기, 위치를 지정하고 

imageView.image = UIImage(named:"파일명")으로 이미지를 불러온다~

 

 

다른 요소들도 앞에서 작성한것처럼 컴포넌트를 생성해준다

//
//  WelcomeViewController.swift
//  34th-Sopt-Seminar
//
//  Created by 김민서 on 2024/03/31.
//

import Foundation
import UIKit

class WelcomeViewController:UIViewController{
    
    var id:String?
    
    private let imageView : UIImageView = {
        let imageView = UIImageView(frame: CGRect(x: 112, y: 87, width: 150, height: 150))
        imageView.image = UIImage(named:"puppy.png")
        
        return imageView
    }()
    
    private let welcomeLabel: UILabel = {
        let label = UILabel(frame: CGRect(x: 140, y: 295, width: 95, height: 60))
        label.text = "???님\n반가워요!"
        label.textColor = .black
        label.textAlignment = .center
        label.numberOfLines = 2
        label.font = UIFont(name:"Pretendard-ExtraBold",size:25)
        return label
    }()
  
    private lazy var mainButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 20, y: 426, width: 335, height: 58))
        button.backgroundColor = UIColor(red: 255/255, green: 111/255, blue: 15/255, alpha: 1)
        button.setTitle("메인으로", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont(name:"Pretendard-Bold",size:18)
        button.layer.cornerRadius = 6
        return button
    }()
    
    private lazy var backTologinButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 20, y: 498, width: 335, height: 58))
        button.backgroundColor = UIColor(red: 221/255, green: 222/255, blue: 227/255, alpha: 1)
        button.setTitle("다시 로그인", for: .normal)
        button.setTitleColor(UIColor(red: 172/255, green: 176/255, blue: 185/255, alpha: 1), for: .normal)
        button.layer.cornerRadius = 6
        button.titleLabel?.font = UIFont(name:"Pretendard-Bold",size:18)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.backgroundColor = .white
        [imageView,welcomeLabel,mainButton,backTologinButton].forEach{
            self.view.addSubview($0)
        }
    }
    
   
}

 

화면 전환(1)

두 개의 화면을 만들었으니 이제 화면을 전환할 수 있도록 연결해보자!

 

1️⃣ presentToWelcomeVC()

: 모달 방식으로 화면 띄우기

 private func presentToWelcomeVC(){
        let welcomeViewController = WelcomeViewController()
        welcomeViewController.modalPresentationStyle = .formSheet
        self.present(welcomeViewController, animated: true)
    }

- 이동할 뷰 컨트롤러를 선언해준다

- modalPresentationStyle 속성으로 어떻게 모달 띄울지 설정 (여러가지 방식이 있다)

- present 함수를 사용해 모달 방식으로 화면을 전환해준다

 

2️⃣ pushToWelcomeVC()

: 네비게이션 방식으로 화면 띄우기

 private func pushToWelcomeVC(){
        let welcomeViewController = WelcomeViewController()
        self.navigationController?
            .pushViewController(welcomeViewController, animated:true)
    }

- 이동할 뷰 컨트롤러를 선언해준다

- navigationcontroller로 push를 진행해준다

 

 

버튼을 눌렀을 때 위에서 만든 함수를 호출할 수 있도록 코드 작성하기

@objc
    private func loginButtonDidTap() {
        presentToWelcomeVC()
        //pushToWelcomeVC()
    }

로그인 버튼을 눌렀을 때 앞에서 선언한 함수 중 어떤 방식을 실행할지 선언하기

 

  private lazy var loginButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 21, y: 422, width: 332, height: 58))
        button.backgroundColor = UIColor(red: 255/255, green: 111/255, blue: 15/255, alpha: 1)
        button.setTitle("로그인하기", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont(name:"Pretendard-Bold",size:18)
        button.layer.cornerRadius = 6
        
        //버튼 이벤트
        button.addTarget(self, action: #selector(loginButtonDidTap), for: .touchUpInside)
        return button
    }()

❗️@objc

Swift를 사용한 코드를 Objective-C 코드와 상호작용 시키기 위해 사용

 

❗️#selcetor

함수를 직접 지정해서 실행할 때 사용

 

❗️addTarget 

controlEvent가 수행되었을 때 실행 주체인 Target과 함수를 연결해주는 함수

 

화면 전환(1)

뒤로 가는 화면도 비슷하게 작성해주면 된다~

welcomeViewController에서 작성하기

//이전 화면으로 가기
    @objc
    private func backToLoginButtonDidTap(){
        //nav controller 사용시 dismiss 방식
        if self.navigationController == nil {
               self.dismiss(animated: true)
           } else {//그게 아닐 시 pop 방식
               self.navigationController?.popViewController(animated: true)
           }
    }

만약 네비게이션 방식으로 이동하지 않았다면 dismiss

네비게이션 방식으로 이동하면 popViewController

 

 

데이터 전달하기

 

1️⃣ 입력받을 전역변수 선언 및 데이터 바인딩 함수 구현

var id: String = " "

아이디를 입력받을 전역 변수 선언

 

2️⃣ 화면의 라벨과 받아온 변수를 연결해주는 bindID 함수 선언

private func bindID() {
    self.welcomeLabel.text = "\(id)님 \n반가워요!"
}

 

해당 함수를 ViewDidLoad에서 호출

 

welcomeViewController.id = idTextField.text

LoginVC로 넘어와서 화면 전환을 하기 위한 다음 뷰컨의 객체를 만드는 부분에 접근해, 해당 변수의 값을 바꿔준다

 

 

🚨근데? 에러가 발생

스위프트에서 변수를 선언할때 non-optional 값을 줘야함

 

즉, 어떤 값을 변수에 줘야하지만 지금 처럼 nil 값을 주고 싶다면

Optional 타입을 사용하기!

 

타입명 + ? 

- 값이 할당 되었을 때 그 값을 그대로 가짐

- 옵셔널 변수에 값을 할당되지 않았을 때 nil 가짐

 

 

근데? 또 문제 발생 옵셔널 사용시 Optional(" ")형태로 출력이 되어 안에 있는 내용만 꺼내야함!!

 

옵셔널 바인딩

 

1️⃣ if let

: nil / nil이 아닐 때 두가지로 나눠서 분기처리 가능

 

2️⃣ guard let

: nil이 아닐 때만 유의미한 코드 진행 / nil일 경우 끝 혹은 에러 문구 만 가능

 

//데이터 바인딩 함수 구현
    private func bindID(){
        guard let idText = id else { return }
        self.welcomeLabel.text="\(idText)님 \n반가워요!"
    }

guard let 형식으로 작성

- nil 일때 return

- nil이 아닐 때 넘겨 받은 id 값 사용

 

프로퍼티와 함수 이용

함수를 이용해 private하게 선언된 변수들을 바꾸어 주기

 

1️⃣ setLabelText 함수 만들기

선언했던 전역 변수 id에 함수를 통해 값을 바꾸어 주고 ViewdidLoad 함수 안 bindText() 함수가 실행되게 만드는 과정을 통해 텍스트로 바꾸어 줌

private func setLabelText(id: String?) {
    self.id = id
}

 

2️⃣ LoginViewController에서 해당 함수 값을 넣어주기

id 프로퍼티를 전역변수가 아닌 private하게 선언된 변수로 바꿀 수 있음

//welcomeViewController.id = idTextField.text
welcomeViewController.setLabelText(id: idTextField.text)

 

 

💡생각해보기💡

✅ final 키워드를 왜 사용할까요? 성능적 이점에는 무엇이 있을까요?

 

✅ 접근제어자가 무엇인지 설명하고, 왜 사용해야 될까요?

: 접근 제어는 코드 간 상호 작용 시 파일 혹은 모듈간  접근을 제어할 수 있는 기능

 

왜 써야하나?

1. 외부로부터 데이터를 보호하기 위해서

2. 외부에는 불필요하고 내부적으로만 사용되는 부분을 감추기 위해서

 

접근 수준 키워드를 통해 구현하고  open / public / internal / fileprivate / private 가 있음

 

open (개방 접근 수준)

- 클래스와 클래스의 멤버에서만 사용할 수 있음

- 해당 멤버가 정의된 모듈 밖의 다른 모듈에서도 재정의 할 수 있음

 

public (공개 접근 수준)

- 어디서든 사용할 수 있음

 

internal (내부 접근 수준)

- 소스파일이 속해 있는 모듈 어디에서든 쓰일 수 있음

- 그 모듈을 가져다 쓰는 외부 모듈에서는 접근 불가

- 기본 접근 수준으로 굳이 표기 하지 않아도 됨

 

fileprivate (파일 외부 비공개 접근 수준)

- 요소가 구현된 소스 파일 내부에서만 사용할 수 있음

- 소스파일 외부에서 값이 변경되거나 함수를 호출하면 부작용이 생길 수 있는 경우에 사용하면 좋음

 

private (비공개 접근 수준)

- 가장 한정적인 범위

- 기능을 정의하고 구현한 범위 내에서만 사용할 수 있음

- 같은 소스파일 안에 구현한 다른 타입이나 기능에서도 사용할 수 없음

 

 

그 중에서도 과제에서 쓰인 private을 예시로 말해보겠음!

비공개 접근 수준은 가장 한정적이고  지정된 요소는 그 기능을 정의하고 구현한 범위 내에서만 사용 가능

 

private var id: String?

 private으로 변수 id를 선언해주어서 WelcomeViewController 클래스 외부에서는 접근이 불가능하게 해줌

 

 func setLabelText(id: String?) {
            self.id = id
}

그래서 id 값을 외부에서 설정 할 수 있도록 setLabelText(id:)함수를 선언해줌

 

private func presentToWelcomeVC(){
        let welcomeViewController = WelcomeViewController()
        welcomeViewController.modalPresentationStyle = .formSheet
        welcomeViewController.setLabelText(id: idTextField.text)
        //welcomeViewController.id = idTextField.text
        self.present(welcomeViewController, animated: true)
    }

id는 private으로 선언되어 LoginViewController에서 직접적으로 접근 불가하기 때문에 presentToWelcome 메서드에서 WelcomeViewController 인스턴스의 setLabelText(id:) 메서드를 호출해 id 값을 해당 메서드로 전달해줌 !!

 

사실 이거 이해하는 것도 너무나도 오래 걸려서 나머지 키워드들도 차차 정리해볼게요 ㅜㅜ

 

 lazy var, let으로 프로퍼티를 선언하였는데 둘의 차이점은 무엇일까요? 만약 해당 코드가 없다면 어떻게 될까요

 

 생명주기는 정말 중요합니다! 다시 한번 꼭꼭 정리해주세요!

'Study > iOS' 카테고리의 다른 글

[swift] 타입/기본 연산자/ 조건문/ 반복문  (1) 2024.05.03