[ํํ๋ก์ ํธ 4์ผ์ฐจ] ํํ๋ชจ๋ฌ ๊ตฌํ์ ๋ํ ๊ณ ๋ฏผ
์๋งคํ๊ธฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํํ๋ชจ๋ฌ์ ๋์์ผํ๋ ์ํฉ์ด๋ค.
์ฌ์ค ์ง๋ ํค์ค์คํฌ ์ฑ์ ๊ตฌํํ ๋์๋ ๋น์ทํ๋ค.
๊ทธ์น๋ง ๊ทธ๋๋ณด๋ค ์ง๊ธ ๊ณ ๋ฏผ์ด ๋๋ ๋ถ๋ถ์ด ์๋ค๋ฉด,
์๋งคํ๊ธฐ ๋ฒํผ์ ๋ทฐ์ ์๊ณ ๋ฒํผ์ ๋๋ ์ ๋ addTarget์ผ๋ก ๋ชจ๋ฌ์ ๋์ฐ๋ ค๊ณ ํ๋ค.
์ด๋, ๋ณ๋์ ๋ทฐ์ปจ์ ๋ง๋ค์ง ์๊ณ ํจ์ ์์์ ๋ง๋ค์ด ๋ณด๋ ค๊ณ ํ๋๋ฐ
๋ชจ๋ฌ์ ๊ตฌํํ ๋ ์ฌ์ฉํ๋ present ๋ฉ์๋ UIViewController ํด๋์ค์ ๋ฉ์๋๋ผ
UIView์์๋ ์ง์ ํธ์ถํ ์๊ฐ ์๋ค๊ณ ํ๋ค. ์ด๊ฒ ๋ฌธ์ ๊ฐ ๋ ๊ฒ์ด๋ค...
MovieInfoViewController.swift
MovieInfoView.swift
์ด๋ ๊ฒ ์์ฑํ๋ฉด ์๋์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
์ด ์ค๋ฅ๋ movieInfoVC ์ธ์คํด์ค๋ฅผ ์ด๊ธฐํํ๋ ์์ ์ self๊ฐ ์์ง ์ด๊ธฐํ๋์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, reservationButton์ addTarget ์ค์ ์ init ๋ฉ์๋ ๋ด๋ถ์์ ์ํํ๋๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค.
addTarget์ init ๋ฉ์๋ ๋ด์์ ์ค์ ํ์ฌ, self๊ฐ ์ด๊ธฐํ๋ ํ์ movieInfoVC ์ธ์คํด์ค์ ์ ๊ทผํ ์ ์๊ฒ ํ๋ค.
์ด๋ ๊ฒ ์์น๋ฅผ ๋ฐ๊ฟ ์ฃผ์๋๋ ์ค๋ฅ๋ ์์ด์ก์ผ๋ ํ๋ฉด์ด ์์ง์ด์ง๊ฐ ์๋ ์ค๋ฅ๊ฐ ๋ค์ ๋ฐ์...
MovieInfoView์ MovieInfoViewController ์ฌ์ด์ ๋ช ํํ ์ญํ ๊ตฌ๋ถ์ด ํ์ํฉ๋๋ค. MovieInfoView์์ ๋ชจ๋ฌ์ ์ง์ ๋์ฐ๋ ๊ฒ์ ๋ฐ๋์งํ์ง ์์ ์ ์์ผ๋ฏ๋ก, ์ก์ ์ ์ค์ ํ ๋ MovieInfoViewController์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ๋ ๋์ , ๋ธ๋ฆฌ๊ฒ์ดํธ ๋๋ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ํธ์์ฉ์ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๐ ์ถ๊ฐ) gpt๊ฐ ์ด๋ ๊ฒ ๋งํ ๊ฑด ์ด ๊ตฌ์กฐ๊ฐ ์๋ชป๋ ์ด์ ๋
๋ทฐ์ปจ์์ ๋ทฐ๋ฅผ, ๋ทฐ์์ ๋ทฐ์ปจ์ ํธ์ถํ๊ณ ์๋ ๊ตฌ์กฐ์๋ ๊ฒ...
์ด๋ ๊ฒ ํ๋๊น ์๋์ด ์ ๋๋ค..ใ
์๋๋ ๋ธ๋ฆฌ๊ฒ์ดํธ์ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๋ค๊ณ ํ๋ค.
UIView ๋ด์์ UIButton์ ์ก์ ์ ์ค์ ํ๊ณ ๋ค๋ฅธ ๋ทฐ ์ปจํธ๋กค๋ฌ์ ์ํธ์์ฉ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด์๋ ๋ช ๊ฐ์ง ๋์์ธ ํจํด๊ณผ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด, ํด๋ก์ ์ฝ๋ฐฑ, ๊ทธ๋ฆฌ๊ณ ๋ ธํฐํผ์ผ์ด์ ์ผํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ํฌํจ๋ฉ๋๋ค. ๊ฐ๊ฐ์ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๊ณ , ์ฝ๋ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
1. ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์ ํ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์๊ฒ ์์ ์ ์์ํ๋ ํจํด์ ๋๋ค. ์ด ํจํด์ ์ฌ์ฉํ๋ฉด UIView์ UIViewController ๊ฐ์ ์ํธ์์ฉ์ ๋ช ํํ๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
1. ํ๋กํ ์ฝ ์ ์:
protocol MovieInfoViewDelegate: AnyObject {
func didTapReservationButton()
}
2. ๋ทฐ ํด๋์ค์ ๋ธ๋ฆฌ๊ฒ์ดํธ ํ๋กํผํฐ ์ถ๊ฐ:
class MovieInfoView: UIView {
weak var delegate: MovieInfoViewDelegate?
// ์์ฝํ๊ธฐ ๋ฒํผ
var reservationButton: UIButton = {
let button = UIButton()
button.setTitle("์๋งคํ๊ธฐ", for: .normal)
button.setTitleColor(.mainWhite, for: .normal)
button.backgroundColor = .mainRed
button.layer.cornerRadius = 8
button.addTarget(self, action: #selector(reservationButtonTapped), for: .touchUpInside)
return button
}()
@objc
private func reservationButtonTapped() {
delegate?.didTapReservationButton()
}
}
3. ๋ทฐ ์ปจํธ๋กค๋ฌ์์ ๋ธ๋ฆฌ๊ฒ์ดํธ ์ค์ ๋ฐ ๊ตฌํ:
class YourViewController: UIViewController, MovieInfoViewDelegate {
private let movieInfoView = MovieInfoView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(movieInfoView)
movieInfoView.snp.makeConstraints { $0.edges.equalToSuperview() }
movieInfoView.delegate = self
}
func didTapReservationButton() {
let modalVc = ModalViewController()
if let modal = modalVc.sheetPresentationController {
modal.detents = [.medium()]
}
present(modalVc, animated: true)
}
}
2. ํด๋ก์ ์ฝ๋ฐฑ
ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ก์ ์ด ๋ฐ์ํ์ ๋ ์ํํ ์์ ์ ์ ์ํ ์ ์์ต๋๋ค.
ํด๋ก์ ํ๋กํผํฐ ์ถ๊ฐ
class MovieInfoView: UIView {
var onReservationButtonTapped: (() -> Void)?
// ์์ฝํ๊ธฐ ๋ฒํผ
var reservationButton: UIButton = {
let button = UIButton()
button.setTitle("์๋งคํ๊ธฐ", for: .normal)
button.setTitleColor(.mainWhite, for: .normal)
button.backgroundColor = .mainRed
button.layer.cornerRadius = 8
button.addTarget(self, action: #selector(reservationButtonTapped), for: .touchUpInside)
return button
}()
@objc
private func reservationButtonTapped() {
onReservationButtonTapped?()
}
}
๋ทฐ ์ปจํธ๋กค๋ฌ์์ ํด๋ก์ ์ค์
class YourViewController: UIViewController {
private let movieInfoView = MovieInfoView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(movieInfoView)
movieInfoView.snp.makeConstraints { $0.edges.equalToSuperview() }
movieInfoView.onReservationButtonTapped = { [weak self] in
let modalVc = ModalViewController()
if let modal = modalVc.sheetPresentationController {
modal.detents = [.medium()]
}
self?.present(modalVc, animated: true)
}
}
}
์์ฝ
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด: ๋ทฐ์ ๋ทฐ ์ปจํธ๋กค๋ฌ ๊ฐ์ ๋ช ํํ ์ญํ ๋ถ๋ฆฌ๋ฅผ ์ ์งํ๊ณ , ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
ํด๋ก์ ์ฝ๋ฐฑ: ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ๋ทฐ์ ๋ทฐ ์ปจํธ๋กค๋ฌ ๊ฐ์ ์ํธ์์ฉ์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
Q1: ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์ ์ฌ์ฉํ ๋, ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ weak๋ก ์ ์ธํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์ ์ฌ์ฉํ ๋, ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ weak๋ก ์ ์ธํ๋ ์ด์ ๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์์ ๋๋ค.
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์์๋ ๊ฐ์ฒด ๊ฐ์ ์ํธ์์ฉ์ด ์ฃผ๋ก ์ผ๋์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค. ์๋ฅผ ๋ค์ด, MovieInfoView๊ฐ MovieInfoViewController์๊ฒ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ๋ ๊ฒฝ์ฐ์ ๋๋ค. ๋ง์ฝ ๋ธ๋ฆฌ๊ฒ์ดํธ๊ฐ ๊ฐํ ์ฐธ์กฐ(strong reference)๋ฅผ ๊ฐ์ง๊ฒ ๋๋ฉด, ๋ ๊ฐ์ฒด ๊ฐ์ ์ํ ์ฐธ์กฐ(circular reference)๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ํ ์ฐธ์กฐ๋ ๋ ๊ฐ์ฒด๊ฐ ์๋ก๋ฅผ ๊ฐํ๊ฒ ์ฐธ์กฐํ๊ณ ์์ด ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋์ง ์๋ ์ํฉ์ ์๋ฏธํฉ๋๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ ์ฝํ ์ฐธ์กฐ(weak reference)๋ก ์ ์ธํ์ฌ, ๋ธ๋ฆฌ๊ฒ์ดํธ ๊ฐ์ฒด๊ฐ ๋ ์ด์ ํ์ ์์ ๋ ์ ์ ํ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋ ์ ์๋๋ก ํฉ๋๋ค.
weak var delegate: MovieInfoViewDelegate?
Q2: ํด๋ก์ ์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฐจ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด๊ณผ ํด๋ก์ ์ฝ๋ฐฑ์ ๊ฐ์ฒด ๊ฐ์ ํต์ ์ ์ํด ์ฌ์ฉ๋์ง๋ง, ๊ทธ ์ฌ์ฉ ๋ฐฉ์๊ณผ ๋ชฉ์ ์๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด
๋ชฉ์ : ์ฃผ๋ก ๊ฐ์ฒด ๊ฐ์ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
๊ตฌ์กฐ: ํ๋์ ํ๋กํ ์ฝ์ ํตํด ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ , ์ด๋ฅผ ๊ตฌํํ ๊ฐ์ฒด์๊ฒ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํฉ๋๋ค.
์ฌ์ฉ ์: UITableViewDelegate, UICollectionViewDelegate ๋ฑ.
์ฅ์ :
์ฝ๋์ ๋ชจ๋์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
์ฌ๋ฌ ๋ฉ์๋๋ฅผ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋จ์ :
์ค์ ์ด ๋ค์ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์ต๋๋ค.
๋จ์ํ ์์ ์ ๋ํด ๊ณผํ ์ ์์ต๋๋ค.
ํด๋ก์ ์ฝ๋ฐฑ
// ํด๋ก์ ์ฝ๋ฐฑ ์์
networkManager.fetchData { result in
switch result {
case .success(let data):
// ๋ฐ์ดํฐ ์ฒ๋ฆฌ
case .failure(let error):
// ์ค๋ฅ ์ฒ๋ฆฌ
}
}
๋ชฉ์ : ์ฃผ๋ก ๋จ์ผ ์์ ์ด๋ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
๊ตฌ์กฐ: ํจ์๋ ๋ฉ์๋์ ์ธ์๋ก ํด๋ก์ ๋ฅผ ์ ๋ฌํฉ๋๋ค.
์ฌ์ฉ ์: ๋คํธ์ํฌ ์์ฒญ์ ์๋ฃ ํธ๋ค๋ฌ, ์ ๋๋ฉ์ด์ ์๋ฃ ํธ๋ค๋ฌ ๋ฑ.
์ฅ์ :
๋จ์ผ ์์ ์ ๋ํด ๊ฐ๋จํ๊ณ ๋ช ํํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค์ ์ด ๊ฐ๋จํฉ๋๋ค.
๋จ์ :
์ฌ๋ฌ ์์ ์ ์ฒ๋ฆฌํด์ผ ํ ๊ฒฝ์ฐ ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ ๋ณต์กํด์ง ์ ์์ต๋๋ค.
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ์ฃผ์ํด์ผ ํฉ๋๋ค (ํนํ [weak self] ์บก์ฒ ๋ชฉ๋ก ์ฌ์ฉ).