์๋งคํ๊ธฐ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํํ๋ชจ๋ฌ์ ๋์์ผํ๋ ์ํฉ์ด๋ค.
์ฌ์ค ์ง๋ ํค์ค์คํฌ ์ฑ์ ๊ตฌํํ ๋์๋ ๋น์ทํ๋ค.
๊ทธ์น๋ง ๊ทธ๋๋ณด๋ค ์ง๊ธ ๊ณ ๋ฏผ์ด ๋๋ ๋ถ๋ถ์ด ์๋ค๋ฉด,
์๋งคํ๊ธฐ ๋ฒํผ์ ๋ทฐ์ ์๊ณ ๋ฒํผ์ ๋๋ ์ ๋ 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] ์บก์ฒ ๋ชฉ๋ก ์ฌ์ฉ).