[Swift] Xcode 개발환경(UIView, UIViewController, UINavigationController, Interface Builder, UIKit)

Oni·2023년 9월 4일
0

TIL

목록 보기
17/47
post-thumbnail

원문 포스팅 🔗

지난 2주차 개인 프로젝트(계산기 만들기) 때 나도 모르게 Interface Builder로 개발하는 실습을 한 것 같다...^^
오늘은 Xcode 개발환경을 알아보고 Interface Builder와 코드로 앱에 텍스트나, 이미지, 토글 등 간단한 앱개발을 실습하는 시간을 가졌다.

Xcode 프로젝트를 생성하면 ViewController.Swift 에는 아래 코드가 기본적으로 세팅되어 있으며, 코드를 작성하여 기능을 구현할 수 있다.

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
}

UIView

UIView는 앱의 화면에 나오는 모든 요소들의 기본 클래스를 말하며, UIButton, UILabel, UIImageView, UIWebView, UIScrollView 등이 있다.

// UIView 객체 생성 + 뷰의 위치 및 크기 설정
let myView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

// 뷰의 배경색상 지정
myView.backgroundColor = UIColor.blue

// 뷰를 서브뷰로 추가
self.view.addSubview(myView)

*self.view.addSubView() : 서브뷰로 추가하지 않으면 아무것도 안뜸


UIViewController

터치나 드래그 등 사용자 상호작용(User Interaction)을 처리할 수 있으며, Storyboard를 사용하거나 사용자가 직접 코드를 작성하여 객체를 생성할 수 있다.
*생명주기(viewDidLoad() 등)를 통해서 다양한 매소드와 함께 관리된다. (생명주기 : 실행부터 종료까지)

class MyViewController: UIViewController {
   override func viewDidLoad() {
       super.viewDidLoad()
       // 화면이 로드되었을 때 필요한 초기화 작업
   }
   
   override func viewWillAppear(_ animated: Bool) {
       super.viewWillAppear(animated)
       // 화면이 나타나기 전 필요한 데이터를 설정하거나 기타 초기화 작업
       print("viewWillAppear")
   }
   override func viewDidAppear(_ animated: Bool) {
       super.viewDidAppear(animated)
       // 화면이 나타난 후 사용자 입력 처리 및 다른 작업
       print("viewDidAppear")
   }
   override func viewWillDisappear(_ animated: Bool) {
       super.viewWillDisappear(animated)
       // 다른 화면으로 이동하기 전 필요한 작업
       print("viewWillDisappear")
   }
   override func viewDidDisappear(_ animated: Bool) {
       super.viewDidDisappear(animated)
       // 다른 화면으로 이동한 후 필요한 작업
       print("viewDidDisappear")
   }
}

UINavigationController

stack 형태로ViewController를 관리하며, Push 및 Pop 동작을 처리한다.

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // button 생성
        // (stack으로 쌓이고 pop형태로 나타낼 수 있음)
        let button = UIButton(type: .system)
        button.setTitle("Push View Controller", for: .normal)
        button.addTarget(self, action: #selector(pushViewController), for: .touchUpInside)
        button.frame = CGRect(x: 100, y: 300, width: 200, height: 100)
        self.view.addSubview(button)
        // 버튼을 현재 뷰에 추가
        
    }
    
    // 버튼 눌렀을 때 나오는 뷰
    @objc func pushViewController() {
        let newViewController = UIViewController()
        newViewController.title = "New View Controller"
        newViewController.view.backgroundColor = .white
        navigationController?.pushViewController(newViewController, animated: true)
    }
}

  • 순서대로 : UIView 생성, button 생성, button 눌렀을 때 나오는 뷰

Interface Builder

시각적인 사용자 인터페이스를 설계하는데 사용하며, Main.storyboard에서 열 수 있다. UIButton, UILabel, UITextfield, UIImageView 등 사용할 수 있는 객체를 드래그앤드롭 방식으로 배치하여 앱에서 사용이 가능하다.
*맥 단축키 : command + Shift + L

제목(Title), 색(Foreground), 정렬(Alighment) 등 객체의 속성을 변경할 수 있다.


@IBOutlet, @IBAction

UI 컴포넌트를 생성하고 ViewController에서 사용할 때 꼭 @IBOutlet, @IBAction을 지정해줘야 한다.
지정방식은 이전 포스팅에서 언급된 바와 같이 control + 드래그를 사용하여 해당 부분이 구현될 위치에 넣는다.

Check Point

  • @IBOutlet, @IBAction 가 view controller와 연결되지 않으면 앱이 죽음(crash)
  • storyboard와 viewcontroller가 Custom Class로 연결되었는지 확인
  • 모든 요소들이 연결되어 있는지, 경고 표시 확인 (대소문자 구분)

UIKit

UILabel

텍스트를 화면에 표시(UITextView, UITextField, UIButton)

  • text 프로퍼티를 사용해서 설정 가능
  • 글꼴(font), 크기(size), 색(color) 등
  • 애니메이션 적용 가능
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // label 생성
        let label = UILabel(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
        label.text = "hello~"
        label.textColor = .red
        label.font = .systemFont(ofSize: 20)
        label.textAlignment = .center
        
        self.view.addSubview(label)
        // 해당하는 view에 대한 UI 컴포넌트 요소를 넣어줘야 함!!
        
    }
 
}

UITextField

  • 입력 유형에 따라 다양한 키보드 타입 지원
  • 입력/수정/삭제를 처리하는 함수와 delegate 제공
  • 텍스트 검증 및 입력된 텍스트 저장/취소 가능
  • placeholder를 통해 입력 가이드 제공
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // textField 생성
        let textField = UITextField(frame: CGRect(x: 200, y: 400, width: 100, height: 50))
        textField.placeholder = "입력하세요."
        textField.backgroundColor = .gray
        // 테두리 지정 어떻게 함?
        
        self.view.addSubview(textField)
        
    }
    
}

UIButton

터치 이벤트에 반응하여 작업을 수행

  • @IBAction 기능
  • 스타일, 크기, 텍스트, 이미지, 배경색 등 변경 가능
  • addTarget(_:action:for:)을 통해 버튼 클릭 시 액션 정할 수 있음
class ViewController: UIViewController, UIScrollViewDelegate {
      
    var scrollView: UIScrollView!
    var imageView2: UIImageView!
    
    @IBOutlet weak var Button1: UIButton!
    @IBAction func buttonTouch(_ sender: Any) {
        print("touch Button1")
        self.view.backgroundColor = .darkGray
        /* self.Button1.titleLabel?.textColor = .white
        // Button1 텍스트 컬러는 어떻게 바꾸지?
        // 저거 안바뀌네(왜지?) */
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // button 생성
        // (stack으로 쌓이고 pop형태로 나타낼 수 있음)
        let button = UIButton(type: .system)
        button.setTitle("Push View Controller", for: .normal)
        button.addTarget(self, action: #selector(pushViewController), for: .touchUpInside)
        button.frame = CGRect(x: 150, y: 500, width: 200, height: 100)
        
        self.view.addSubview(button)
        // 버튼을 현재 뷰에 추가
        
    }
    
}

UIImageView

이미지를 화면에 표시

  • image 프로퍼티를 사용해서 이미지 저장
  • 스케일(scale), 크기(size), 위치, 회전, 투명도 조절 가능
  • 이미지 연속 표시, 회전/확대/축소 등 애니메이션 적용 가능
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // image 생성
        let imageView = UIImageView(frame: CGRect(x: 300, y: 500, width: 30, height: 30))
        let image = UIImage(systemName: "folder.fill")
        imageView.image = image
        imageView.contentMode = .scaleAspectFill
        
        self.view.addSubview(imageView)
        
    }
}

UISwitch

  • 토글 형태의 스위치를 조작
  • 스위치를 키거나 끌 수 있어 On/Off 상태 표시 가능
  • onTintColor/thumbTintColor 설정 가능
  • 스위치가 변경될 때 실행될 액션 설정 가능
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // switch 생성
        let myswitch = UISwitch(frame: CGRect(x: 100, y: 600, width: 100, height: 50))
        myswitch.isOn = true
        myswitch.onTintColor = .blue
        myswitch.thumbTintColor = .white
        myswitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged)
        
        self.view.addSubview(myswitch)
        
    }
    
}

UISlider

  • 값을 조정할 수 있는 슬라이더
  • 수평 or 수직으로 표시
  • 최대값, 최소값 설정하여 범위 설정 가능
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let slider = UISlider()
        slider.minimumValue = 0.0
        slider.maximumValue = 100.0
        slider.value = 50.0
        slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)

        @objc func sliderValueChanged() {
            let value = slider.value
            // 슬라이더 값 변경 시 수행할 작업
        }
    }
    
}

UISegmentedControl

  • 여러개의 세그먼트로 구성된 컨트롤
  • addSegment : 추가, selectedSegmentIndex : 선택된 세그먼트 설정
  • 실행될 액션을 addTarget을 통해 설정 가능
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let segmentedControl = UISegmentedControl(items: ["옵션1", "옵션2", "옵션3"])
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged), for: .valueChanged)

        @objc func segmentedControlValueChanged() {
            let selectedIndex = segmentedControl.selectedSegmentIndex
            // 선택된 세그먼트에 대한 작업 수행
        }
        
    }
    
}

UIScrollView

  • 사용자가 스크롤하여 뷰 내 컨텐츠를 볼 수 있게 함
  • UIScrollViewDelegate 프로토콜을 사용하여 스크롤 이벤트 처리 및 컨텐츠 추가/제거 가능
  • 다중 제스처 지원(tap, swipe, rotate 등)
class ViewController: UIViewController, UIScrollViewDelegate {
    
    var scrollView: UIScrollView!
    var imageView2: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // srcollview 생성
        scrollView = UIScrollView(frame: CGRect(origin: CGPoint(x: 0, y: 400), size: CGSize(width: view.bounds.width, height: 200)))
        scrollView.delegate = self
        // UIScrollViewDelegate 클래스 추가해줘야 함
        // delegate : 특정 사용자 인터랙션에 대해 반응하는 프로토콜
        
        imageView2 = UIImageView(image: image)
        imageView2.contentMode = .scaleAspectFit
        imageView2.frame = CGRect(origin: .zero, size: CGSize(width: 100, height: 100))
        scrollView.addSubview(imageView2)
        scrollView.contentSize = CGSize(width: view.bounds.width*2, height: 100)
        scrollView.minimumZoomScale = 0.5
        scrollView.maximumZoomScale = 2.0
        
        view.addSubview(scrollView)
        
    }
    
    // scrollview 줌인/줌아웃 함수 추가
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imageView2
    }

}

UIPickerView

  • 목록에서 값을 선택할 수 있음
  • 여러개의 열(column)로 구성, 각 열에는 여러개의 행(row) 포함
  • UIPickerViewDataSource 프로토콜 : 데이터 소스 구현
  • UIPickerViewDelegate 프로토콜 : 델리게이트 메서드 구현
  • didSelectRow : 선택된 값을 가져올 수 있음
class ViewController: UIViewController, UIScrollViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
    
    var scrollView: UIScrollView!
    var imageView2: UIImageView!
    let pickerView = UIPickerView()
    let data = ["항목1", "항목2", "항목3"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // pickerView 생성
        pickerView.frame = CGRect(x: 200, y: 100, width: 200, height: 200)
        self.view.addSubview(pickerView)
        pickerView.dataSource = self
        // UIPickerViewDataSource 클래스 추가
        pickerView.delegate = self
        // UIPickerViewDelegate 클래스 추가
        
    }
    
    // pickerView 갯수
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return data.count
    }
    
    // pickerView 선택항목 갯수
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    // pickerView 어떤 값을 row로 가져올 건지?(앞에서 선언한 data 배열을 가져옴)
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return data[row]
    }
    
    // pickerView 선택됐을 때 콘솔창에 띄울 사항
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        let selectedValue = data[row]
        print("선택 : ", selectedValue)
    }
}

UITableView

  • 리스트 형식의 데이터를 표시
  • 여러개의 섹션을 가지며, 각 섹션은 여러개의 행을 가짐
  • UITableViewDataSource : 데이터 제공
  • UITableViewDelegate : 행을 사용자에게 표시
  • 행을 재사용하여 메모리 사용량을 줄일 수 있음
  • 행 선택 및 삭제 가능
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // data 생성
    let data = ["apple", "banana", "cherry", "durian", "elderberry"]
    var tableView: UITableView!
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // tableView 생성
        tableView = UITableView(frame: view.bounds, style: .plain)
        tableView.dataSource = self
        tableView.delegate = self
        
        view.addSubview(tableView)
    }
    
    // 행으로 불러올 셀은 어떤 값인지 -> data 배열을 행으로 가져옴
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
        cell.textLabel?.text = data[indexPath.row]
        return cell
    }
    
    // 행이 몇개인지
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    // 앱의 값을 확인
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("선택 : ", data[indexPath.row])
    }
    
    
}

UICollectionView

  • 그리드 형식으로 데이터를 표시
  • 여러개의 섹션을 가지며, 각 섹션은 여러개의 셀을 가짐
  • UICollectionViewFlowLayout class : 셀 크기 및 간격 조정
  • 셀을 재사용하여 메모리 사용량을 줄일 수 있음
  • 셀 선택 및 삭제 가능



내일은 각 코드에 주석으로 달아논 안되는 부분에 대한 해결과 개인 프로젝트 기획을 진행할 예정이다.
2주차 때 계산기 만들면서 이것저것 클릭해본게 도움이 된 것 같다..

profile
하지만 나는 끝까지 살아남을 거야!

0개의 댓글