#1. StoryBoard by MVC
: viewDidLoad에 datasource와 delegate 꼭 해줘야됨.
Models: struct와 manager
Views: UITableViewCell과 Main.storyboard
Controllers: ViewController와 DetailViewController
— 데이터를 가져오는 방법 —
#1
var moviesArray: [Movie] = [] // 테이블 뷰의 데이터를 표시하기 위한 배열
// viewdidload에
movieDataManager.makeMovieData() // 일반적으로는 서버에 요청
moviesArray = movieDataManager.getMovieData() // 데이터를 받아서 뷰컨의 배열에 저장
#2
var movieDataManager = DataManager() // MVC패턴을 위한 데이터 매니저(배열 관리 - 데이터)
// viewDidload에
movieDataManager.makeMovieData()
— 새로운 컨텐츠를 추가하고 싶을때 —
@IBAction func addButtonTapped(_ sender: UIBarButtonItem) {
movieDataManager.updateMovieData()
tableView.reloadData()
— DataSource delegate
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(#function) // 테이블 뷰에 몇 개의 데이터를 표시할 것인지(셀이 몇개인지)를 뷰컨트롤러에게 물어봄
// return moviesArray.count
return movieDataManager.getMovieData().count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(#function) // 셀의 구성(셀에 표시하고자 하는 데이터 표시)을 뷰컨트롤러에게 물어봄
// IndexPath에는 section과 row가 있다.
// (힙에 올라간) 재사용 가능한 셀을 꺼내서 사용하는 메서드
// (사전에 셀을 등록하는 과정이 내부 메커니즘에 존재)
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath) as! MovieCell
let array = movieDataManager.getMovieData()
let movie = array[indexPath.row]
cell.mainImageView.image = movie.movieImage
cell.movieNameLabel.text = movie.movieName
cell.descriptionLabel.text = movie.movieDescription
cell.selectionStyle = .none
return cell
}
}
— UITableViewDelegate —
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// 어떠한 셀이 선택 되었을때 어떤 동작을 할 것인지 뷰컨트롤러에게 물어봄
performSegue(withIdentifier: "toDetail", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toDetail" {
let detailVC = segue.destination as! DetailViewController
let array = movieDataManager.getMovieData()
let indexPath = sender as! IndexPath
detailVC.movieData = array[indexPath.row]
}
}
}
#2. programmatically by MVC
: SceneDelegate에 UINavigationController
// func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// guard let windowScene = (scene as? UIWindowScene) else { return }
// window = UIWindow(windowScene: windowScene)
let naviVC = UINavigationController(rootViewController: ViewController()) // 네비게이션컨트롤러(네비게이션바 설정하는 방법?)
window?.rootViewController = naviVC
window?.makeKeyAndVisible()
}
Models: struct와 manager
Views: UITableViewCell과 UIView(DetailView)
Controllers: ViewController 2개(하나는 셀을 눌렀을때 넘어가는 DetailViewController)
import UIKit
final class MyTableViewCell: UITableViewCell {
let mainImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let movieNameLabel: UILabel = {
let label = UILabel()
label.font = UIFont.boldSystemFont(ofSize: 17)
return label
}()
let descriptionLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 17)
label.numberOfLines = 0
return label
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.axis = .vertical
sv.distribution = .fill
sv.alignment = .fill
sv.spacing = 8
return sv
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: reuseIdentifier)
setupStackView()
}
func setupStackView() {
self.addSubview(mainImageView)
// 뷰컨트롤러의 기본뷰 위에 스택뷰 올리기
self.addSubview(stackView)
// 스택뷰 위에 뷰들 올리기
stackView.addArrangedSubview(movieNameLabel)
stackView.addArrangedSubview(descriptionLabel)
}
**// 중요한 부분**
**required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}**
// 오토레이아웃 정하는 정확한 시점
override func updateConstraints() {
setConstraints()
super.updateConstraints()
}
func setConstraints() {
setMainImageViewConstraints()
setMovieNameLabelConstraints()
setStackViewConstraints()
}
func setMainImageViewConstraints() {
NSLayoutConstraint.activate([
mainImageView.heightAnchor.constraint(equalToConstant: 100),
mainImageView.widthAnchor.constraint(equalToConstant: 100),
mainImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10),
mainImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor)
])
}
func setMovieNameLabelConstraints() {
movieNameLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
movieNameLabel.heightAnchor.constraint(equalToConstant: 22)
])
}
func setStackViewConstraints() {
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: mainImageView.trailingAnchor, constant: 15),
stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
stackView.topAnchor.constraint(equalTo: self.mainImageView.topAnchor),
stackView.bottomAnchor.constraint(equalTo: self.mainImageView.bottomAnchor)
])
}
}
import UIKit
final class DetailView: UIView {
let mainImageView: UIImageView = {
let imageView = UIImageView()
return imageView
}()
let movieNameLabel: UILabel = {
let label = UILabel()
label.font = UIFont.boldSystemFont(ofSize: 22)
return label
}()
let descriptionLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 17)
label.numberOfLines = 0
return label
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.axis = .vertical
sv.distribution = .fill
sv.alignment = .fill
sv.spacing = 15
return sv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
setupStackView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupStackView() {
// 스택뷰 위에 뷰들 올리기
stackView.addArrangedSubview(mainImageView)
stackView.addArrangedSubview(movieNameLabel)
stackView.addArrangedSubview(descriptionLabel)
// 뷰컨트롤러의 기본뷰 위에 스택뷰 올리기
self.addSubview(stackView)
}
// 오토레이아웃 업데이트
override func updateConstraints() {
setConstraints()
super.updateConstraints()
}
func setConstraints() {
setMainImageViewConstraints()
setMovieNameLabelConstraints()
setDescriptionLabelConstraints()
setStackViewConstraints()
}
func setMainImageViewConstraints() {
mainImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
mainImageView.heightAnchor.constraint(equalToConstant: 240),
mainImageView.widthAnchor.constraint(equalToConstant: 240)
])
}
func setMovieNameLabelConstraints() {
movieNameLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
movieNameLabel.heightAnchor.constraint(equalToConstant: 30)
])
}
func setDescriptionLabelConstraints() {
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
descriptionLabel.heightAnchor.constraint(equalToConstant: 100)
])
}
func setStackViewConstraints() {
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
stackView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 100)
])
}
}
func setupNaviBar() {
title = "영화목록"
// (네비게이션바 설정관련) iOS버전 업데이트 되면서 바뀐 설정⭐️⭐️⭐️
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground() // 불투명으로
appearance.backgroundColor = .white
navigationController?.navigationBar.tintColor = .systemBlue
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.compactAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
}
func setupTableView() {
// 델리게이트 패턴의 대리자 설정
tableView.dataSource = self
tableView.delegate = self
// 셀의 높이 설정
tableView.rowHeight = 120
// 셀의 등록과정⭐️⭐️⭐️ (스토리보드 사용시에는 스토리보드에서 자동등록)
// tableView.register(<#T##cellClass: AnyClass?##AnyClass?#>, forCellReuseIdentifier: <#T##String#>) // 여기서 MovieCell을 적용해줘서 아래에서 사용가능 한 것임.
tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "MovieCell")
// 메타 타입: 타입 인스턴스의 타입을 의미함, 붕어빵 틀을 입력하는것(인스턴스를 넣는 것이 아님)
}
func setupDatas() {
movieDataManager.makeMovieData() // 일반적으로는 서버에 요청
moviesArray = movieDataManager.getMovieData() // 데이터 받아서 뷰컨의 배열에 저장
}
// 테이블뷰의 오토레이아웃 설정
func setupTableViewConstraints() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0),
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
])
}
}