스탠다드 반 강의 (복습)
스파르타 코딩 클럽
우선 코드베이스로 구현하려면 프로젝트를 생성 후, 메인 스토리보드를 삭제하고,
info에서 StoryboardName 부분에 Main으로 설정되어 있는 것을 지우고,
SceneDelegate 파일에서 ViewController를 연결해 주는 작업이 필요하다
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene) //SceneDelegate의 프로퍼티에 설정( var window:UIWindow? )
let mainViewController = ViewController() // 처음 보여줄 ViewController 인스턴스 생성
window?.rootViewController = mainViewController //window.rootViewController에 생성한 ViewController 넣기
window?.makeKeyAndVisible()
: 앱에 대한 하나 이상의 창을 관리하는 뷰
: 앱의 사용자 인터페이스에 대한 배경과 이벤트를 뷰에 전달하는 개체
ㄴ windowScene : The scene object in which to display the window.
: 윈도우를 표시하고 키 윈도우로 만듦
( 현재 창을 표시하고 같은 수준 이하의 다른 모든 창 앞에 배치하는 편리한 방법)
* Exception NSException * "Invalid parameter not satisfying: [name length] > 0" 0x00006000024690b0
ㄴ 실행했더니 이런 에러가 떠서 검색해 본 결과
ㄴ info에서 Storyboard Name 행 자체를 삭제하면 해결된다고 한다 !
또 에러 떠서 검색해 봤더니 이것도 삭제해줘야 하는 것 같다..
* 스탠다드 반 강의 들으면서 하는 게 낫겠다 싶어서 ,, 스탠다드반 강의 다시 들어보려 했는데
아핳.. 그렇구나.. ㅜ
view.backgroundColor를 지정 안 해줘서 그런 거였다.. !
backgroundColor 설정해 주면 잘 나오는 것을 확인할 수 있음 !
UIComponent 초기화
import UIKit
class ViewController : UIViewController {
let titleLabel = UILabel()
let mytableView = UITableView()
let addButton = UIButton()
let button1 = UIButton()
let button2 = UIButton()
let button3 = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
}
}
IBOutlet처럼 UIComponent 초기화 과정이 필요하다
addSubView()
: View에 요소를 추가해 주는 작업 ! ( viewDidLoad에 해줌 )
ㄴ 계층 구조가 만들어져 부모 - 자식 관계가 됨
ㄴ 주어진 뷰를 현재 뷰의 하위 뷰로 추가하는 것 ("superView"에 대해 "addSubview"를 호출하면 그 뷰의 하위에 새로운 뷰 추가)
import UIKit
class ViewController : UIViewController {
//생략
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(titleLabel)
view.addSubview(tableView)
view.addSubview(addButton)
view.addSubview(button1)
view.addSubview(button2)
view.addSubview(button3)
}
}
* 요소가 많으면 길어지기 때문에 배열에 담아서 사용할 수 있음 !
[titleLabel,myTableView,addButton].forEach {
view.addSubview($0)
}
* 순서가 중요 !
ㄴ 배경 이미지 위에 버튼을 보여주고 싶은 경우, 이미지를 먼저 올려주는 식으로 순서를 잘 지켜줘야 한다
StackView 코드로 추가
stackView.addArrangedSubview(button1,button2,button3)
[button1,button2,button3].forEach {
stackView.addArrangedSubView($0)
}
* 배열 사용
TableView 코드로 추가
: 스토리보드에서는 register에서 Nib 어쩌고를 사용했었는데 CellClass를 사용해 주면 된다!
myTableView.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.identifier)
Cell
기존에 xib에서 사용해 줬던 awakeFromNib 메서드는 이제 필요 없어지고, init 오버라이드를 해야 한다.
import UIKit
class MyTableViewCell : UITableViewCell {
let static identifier = "MyTableViewCell" //identifier 미리 등록
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:)has not been implemented")
}
}
* cell에서는 view에 접근을 할 수 없다 -> contentView (뷰컨트롤러에 view. 역할)
import UIKit
class MyTableViewCell : UITableViewCell {
let myLabel = UILabel()
let static identifier = "MyTableViewCell" //identifier 미리 등록
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(myLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:)has not been implemented")
}
}
그냥 간단하게 레이블 추가해 보는 연습!
오토레이아웃 안 잡아주면 화면에 안 나옴,, ㅠㅠ
그래서 일단 아무렇게나 잡아줬는데 저건 중앙에 맞춰주는 오토레이아웃인 것 같다!
코드 정리하는 법
- 함수로 묶어서 viewDidLoad()에 추가해 주면 더 깔끔한 코드로 정리할 수 있다.
ㄴ setupContraints() -> addSubView, 오토레이아웃을 모은 함수
ㄴ configureUI() -> UI 요소들의 속성 모음 함수
* 이건 예시이고, 자신이 원하는 대로 메서드 정의할 수 있음
//addSubView, 오토레이아웃 모음 함수
func setupConstraints() {
//addSubView
[titleLabel,myTableView,addButton].forEach {
view.addSubview($0)
}
//오토레이아웃
}
//UI 요소들의 속성 모음 함수
func configureUI() {
view.backgroundColor = .white
titleLabel.text = "제목 레이블"
titleLabel.backgroundColor = .green
myTableView.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.identifier)
}
override viewDidLoad() {
super.viewDidLoad()
setupConstraints()
configureUI()
}
BaseViewController
: 메서드 이름을 맞추는 것이 중요한데,, BaseViewController를 상속받아서 활용하면 굳!
import UIKit
class BaseViewController : UIVIewController {
super.viewDidLoad()
setupConstraints()
configureUI()
}
func setupConstraints() {
// 내용
}
func configureUI() {
// 내용
}
이렇게 새로운 파일을 만들어서 함수와 함수를 사용하는 부분을 작성해 주고, ViewController : BaseViewController 즉, BaseViewController를 상속받도록 해주면 ViewController에서 그냥 저 함수를 입력해 줄 필요도 없이 깔끔하게 사용할 수 있다.
import UIKit
class ViewController : BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
//setupConstraints()와 configureUI()를 안 적어줘도 됨 !
}
override func setupConstraints() {
super.setupConstraints()
}
override func configureUI(){
super.configureUI()
}
}
* override 된 function은 super을 불러야 한다!
Constraints 잡아주기
1. translatesAutoresizingMaskIntoConstraints = false
ㄴ 간단하게 기기에 맞춰서 크기 조절을 해주는 기능 (동적으로 크기와 위치를 조절하려면 false 상태로 두어야 한다)
ㄴ 오토레이아웃을 설정해 주기 위해 끄는 것!
textLabel.translatesAutoresizingMaskIntoConstraints = false
2. anchor 연결
요소.어디 쪽에 Anchor을 줄 건지.constraint(equalTo:앞에 정한 Anchor에서 비교될 부분, constant:얼마큼 떨어지게 할 것인지).isActive = true
textLabel.topAnchor.constraint(equalTo:view.safeAreaLayoutGuide.topAnchor, constant:30).isActive = true
view.safeAreaLayoutGuide.topAnchor 은 SafeArea의 top 부분을 뜻함
즉, textLabel의 topAnchor가 SafeArea의 top에 걸렸다는 뜻인데, 30만큼 준다는 의미
* centerXAnchor, centerYAnchor : 센터 잡기
* trailingAnchor를 줄 때 주의할 점
뷰의 방향은 이런 식이라서 trailing을 잡을 때 +30을 주면 밖으로 빠져나간 30을 의미하게 됨. 따라서 안쪽에 여백을 주려면 -30을 줘야 한다.
실습
SafeArea에서 textLabel top이 30만큼 떨어져 있고, leading과 trailing은 양쪽으로 20씩, textLabel의 높이를 50으로 정해줘서 오토레이아웃을 맞춰주었다!
코드를 정리해 보자면
이런 식으로 할 수 있음! 실행해 보면 위 화면과 동일하게 잘 실행된다!