지난 2주차 개인 프로젝트(계산기 만들기) 때 나도 모르게 Interface Builder로 개발하는 실습을 한 것 같다...^^
오늘은 Xcode 개발환경을 알아보고 Interface Builder와 코드로 앱에 텍스트나, 이미지, 토글 등 간단한 앱개발을 실습하는 시간을 가졌다.
Xcode 프로젝트를 생성하면 ViewController.Swift 에는 아래 코드가 기본적으로 세팅되어 있으며, 코드를 작성하여 기능을 구현할 수 있다.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
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() : 서브뷰로 추가하지 않으면 아무것도 안뜸
터치나 드래그 등 사용자 상호작용(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")
}
}
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)
}
}
시각적인 사용자 인터페이스를 설계하는데 사용하며, Main.storyboard에서 열 수 있다. UIButton, UILabel, UITextfield, UIImageView 등 사용할 수 있는 객체를 드래그앤드롭 방식으로 배치하여 앱에서 사용이 가능하다.
*맥 단축키 : command + Shift + L
제목(Title), 색(Foreground), 정렬(Alighment) 등 객체의 속성을 변경할 수 있다.
UI 컴포넌트를 생성하고 ViewController에서 사용할 때 꼭 @IBOutlet, @IBAction을 지정해줘야 한다.
지정방식은 이전 포스팅에서 언급된 바와 같이 control + 드래그를 사용하여 해당 부분이 구현될 위치에 넣는다.
Check Point
- @IBOutlet, @IBAction 가 view controller와 연결되지 않으면 앱이 죽음(crash)
- storyboard와 viewcontroller가 Custom Class로 연결되었는지 확인
- 모든 요소들이 연결되어 있는지, 경고 표시 확인 (대소문자 구분)
UILabel
텍스트를 화면에 표시(UITextView, UITextField, UIButton)
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
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
터치 이벤트에 반응하여 작업을 수행
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
이미지를 화면에 표시
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
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
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
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
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
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
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
내일은 각 코드에 주석으로 달아논 안되는 부분에 대한 해결과 개인 프로젝트 기획을 진행할 예정이다.
2주차 때 계산기 만들면서 이것저것 클릭해본게 도움이 된 것 같다..