코드로 뷰를 구성한 경험은 몇번 있지만 스토리 보드로 화면을 구성하는 익숙해져서 다시 기억속에서 사라졌다 ㅠ.ㅠ
아무래도 지금 다니는 회사에서는 스토리보드로 화면을 구성하니 스토리보드는 따로 연습하지 않아도 익숙해질 수 밖에 없는 환경이기 때문에 혼자서 하는 연습 예제나 프로젝트는 코드로 구성하는 방법으로 해봐야겠다!
구성한 화면은 아래와 같다.
UIViewController - UIView - UIView - UIButton 으로 구성되어 있다. 조금 더 자세히 보자면 ...
이런 계층으로 구성되어 있다. (이 기능 너무 좋다 🫶🏻)
먼저 화면을 구성하는 전체적인 틀은 다음과 같다.
// 새로운 뷰 생성
let newView = UIView()
// 기본 뷰에 추가
view.addSubview(newView)
// 오토 레이아웃을 사용하여 위치와 크기 지정
newView.translatesAutoresizingMaskIntoConstraints = false
// 위쪽 제약 조건
newView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
// 아래쪽 제약 조건
newView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// 왼쪽 제약 조건
newView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
// 오른쪽 제약 조건
newView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
1. 화면에 올려줄 뷰 생성
2. View 추가 (addSubview())
3. 오토레이아웃 설정
이걸 순서대로 안해주면 이런 에러를 마주칠 수 있다!
That's illegal... -> 내가 작성한 것과 같이 오토레이아웃 설정 후 addSubview를 하면 요런 에러를 마주치니 주의하쟈! (생각해보면 당연히 뷰를 추가하고 오토레이아웃을 설정하는게 맞다..~!)
// PushView.swift
import UIKit
class PushView: UIView {
private lazy var pushView: UIView = {
let view = UIView()
view.backgroundColor = .cyan
view.addSubview(pushBtn)
return view
}()
lazy var pushBtn: UIButton = {
let btn = UIButton()
btn.setTitle("Push", for: .normal)
btn.addTarget(self, action: #selector(touchPushBtn), for: .touchUpInside)
return btn
}()
@objc func touchPushBtn() {
print("tap push button in UIView")
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(pushView)
setConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setConstraints() {
pushView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
pushView.topAnchor.constraint(equalTo: topAnchor),
pushView.leadingAnchor.constraint(equalTo: leadingAnchor),
pushView.trailingAnchor.constraint(equalTo: trailingAnchor),
pushView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
pushBtn.translatesAutoresizingMaskIntoConstraints = false
pushBtn.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
pushBtn.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
}
// PushViewController.swift
import UIKit
final class PushViewController: UIViewController {
private let pushView = PushView()
override func loadView() {
view = pushView
}
override func viewDidLoad() {
super.viewDidLoad()
setAddTarget()
}
func setAddTarget() {
pushView.pushBtn.addTarget(self, action: #selector(tapPresentBtn), for: .touchUpInside)
}
@objc func tapPresentBtn() {
print("tap push button in UIViewController")
}
}
나는 이렇게 뷰와 뷰컨트롤러를 작성해주었다.
그리고 storyboard는 없애도 되지만 요기서는 storyboard는 없애지 않고 시작할 뷰 컨트롤러만 연결해준 상태이다!
하나 더 내가 궁금했던 부분이 있었는데, UIView와 UIViewController에서 모두 버튼의 addTarget를 설정할 수 있어서 어떤 기준으로 이걸 결정해서 작성하는지 궁금했다.
결론은 두 곳 어디에 작성해도 상관은 없는데, 내가 UIView와 UIViewController를 다른 파일로 분리한 이유와 같이 디자인 패턴(MVC 사용)에서의 이유가 있다.
UIView는 화면을 관리하기 위한 코드를 작성하는 부분이기 때문에 예를들어서 버튼을 클릭하면 화면의 색상이 변한다는등.. 이런 처리는 UIView에서 버튼의 addTarget를 설정하는것이 맞고, View를 이동하는것과 같은 동작은 UIView가 아닌 UIViewController에서 하는게 맞다고 생각한다. (UIView에서 Push나 Present를 하면 이상하니까..)
그리고 두곳 다 addTarget를 사용해 함수를 실행하면 (위에 코드 실행 버튼 터치 후 결과)
이처럼 UIView에 있는 버튼의 함수가 먼저 작동한다 (참고)
이거 작성하면서 이 내용들은 다 익혔지만~~ 또 몇주 지나면 까먹을 수 있으니 또 까먹으면 이거 보고 다시 익혀야겠다~
'iOS' 카테고리의 다른 글
[iOS] ReactiveX란? / RxSwift 기초 익히기 (0) | 2023.05.08 |
---|---|
[iOS] 뷰를 push, present 하는 과정에서 이전 navigation controller에 접근해 뷰 push하기 (0) | 2023.04.20 |
[iOS] xcode Vary for Traits (0) | 2023.03.28 |
[iOS] 델리게이트 패턴 (Delegate Pattern) (0) | 2023.03.18 |
[iOS] OAuth Login firebase와 연동하면서 알게된 점 (Apple, Google, Email, Kakao) (0) | 2022.12.23 |