-
[Swift] Delegate, Notification, KVOSwift 2022. 3. 15. 08:50
์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์ ํํ ๊ฒฝํํ๋ ๊ณตํต์ ์ธ ๋ฌธ์ ๋ ๊ณผ๋ํ ์ปคํ๋ง ์์ด ์ปจํธ๋กค๋ฌ ๊ฐ์ ์ํต์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. iOS์์ ๋ํ๋ด๋ 3๊ฐ์ง ์ผ๋ฐ์ ์ธ ํจํด์ ๋ค์๊ณผ ๊ฐ๋ค.
- Delegation
- Notifications through Notification Center
- Key Value Observing
3๊ฐ์ง ํจํด์ด ๋์ค๊ฒ ๋ ๋ฐฐ๊ฒฝ
๐ก ํ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฌถ์ด๊ธฐ (coupled)๋ ์ซ์ง๋ง, ์ํต์ ํ๊ณ ์ถ์ ๋
3๊ฐ์ง ํจํด์ ๋ชจ๋ ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด ์ํ๋ ๊ฐ์ฒด์ ์๋ ค์ฃผ๊ณ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
์ดํ๋ฆฌ์ผ์ด์ ํน์ฑ ์ ๊ฐ์ฒด ๊ฐ ์ํต์ ํ์์ ์ด์ง๋ง ํ ๊ฐ์ฒด๋ ๊ทธ ์์ฒด๋ก ์กด์ฌํ๋ฉด์ ์ํตํ ๋ฟ, ๋ค๋ฅธ ๊ฐ์ฒด์ ์ข ์๋์ด ๋์ํ๋ ๊ฒ์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๋ ๋ฆฝ๋ ๊ธฐ๋ฅ์์ ์ธก๋ฉด์์ ์ข์ง ์๋ค.
์๋ฅผ ๋ค๋ฉด ์ฐ๋ฆฌ๋ ํ VC๊ฐ ๋ค๋ฅธ VC์ ๊ฒฐํฉํ์ง ์๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ์กด์ฌํ๊ธฐ๋ฅผ ๋ฐ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Delegation, Notification, KVO๋ฅผ ์ฌ์ฉํ๋ค.
1. Delegate
- Delegate๋ Protocol์ ์ ์ํ์ฌ ์ฌ์ฉํ๋ค.
- Protocol์ Delegate๋ก ์ง์ ๋ ๊ฐ์ฒด๊ฐ ์ฌ์ฉํ ๋ฉ์๋๋ค์ ๊ตฌํ์ ํ์ง ์๊ณ ์ ์๋ง ํ๋ค.
- Delegate๋ก ์ง์ ๋ ๊ฐ์ฒด๋ ์ด ํ๋กํ ์ฝ์ ์ฑํํ๊ณ , ํ๋กํ ์ฝ์ ์ ์๋ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋ค.
- ๊ฐ์ฒด๋ ์ด๋ฒคํธ ๋ฐ์ ์ Delegate๋ก ์ง์ ๋ ๊ฐ์ฒด์๊ฒ ์๋ฆฌ๊ณ , Delegate๋ก ์ง์ ๋ ๊ฐ์ฒด๊ฐ ์ด๋ฒคํธ๋ฅผ ๋์ ์ฒ๋ฆฌํ๋ค. ๊ฐ์ฒด๋ ์์ ์ delegate๊ฐ ๋๊ตฌ์ธ์ง ์์ง ๋ชปํ๋ค.
- ์ฃผ๋ก 1:1๋ก ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ ๋ ์ฌ์ฉํ๋ค.
// #1. ํ๋กํ ์ฝ ์ ์ protocol SideViewDelegate { func sideViewButtonDidTapped(_ button: UIButton) } class SideView: UIView { // #2. ๋ค๋ฅธ ๊ฐ์ฒด์๊ฒ ๊ธฐ๋ฅ์ ์์ํ๊ธฐ ์ํ delegate ํ๋กํผํฐ var delegate: SideViewDelegate? @objc func sideViewButtonTapped(_ sender: UIButton) { // #3. SideView์ Delegate๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ delegate ํ๋กํผํฐ๋ฅผ ํตํด sideViewButtonDidTapped ๋ฉ์๋๋ฅผ ์คํ์ํจ๋ค. delegate?.sideViewButtonDidTapped(sender) } } class ViewController: UIViewController { let sideView: SideView = { let view = SideView() view.translatesAutoresizingMaskIntoConstraints = false return view }() override func viewDidLoad() { super.viewDidLoad() // #6. sideView์ delegate ์ญํ ์ ํ๋ VC sideView.delegate = self } } // #4. Delegate ์ฑ์ฉ extension ViewController: SideViewDelegate { // #5. ํ๋กํ ์ฝ์ ์ ์๋ ๋ฉ์๋ ๊ตฌํ func sideViewButtonDidTapped(_ button: UIButton) { print("SideView์ Button์ด Tapped๋์์ด์ฉ") } }์ฅ์
- ์๊ฒฉํ Syntax๋ก ์ธํด ํ๋กํ ์ฝ์ ํ์ํ ๋ฉ์๋๋ค์ด ๋ช ํํ ๋ช ์๋๋ค.
- ์ปดํ์ผ ์ ๊ฒฝ๊ณ /์๋ฌ๋ก ๊ตฌํ๋์ง ์์ ํ๋กํ ์ฝ์ ๋ฉ์๋๋ฅผ ์๋ ค์ค๋ค.
- ํ๋กํ ์ฝ์ด ์ปจํธ๋กค๋ฌ ๋ฒ์ ๋ด์์ ์ ์๋๋ค.
- ๋ก์ง์ ํ๋ฆ์ ๋ฐ๋ผ๊ฐ๊ธฐ ์ฝ๋ค.
- ํ๋กํ ์ฝ ๋ฉ์๋๋ก ์๋ ค์ฃผ๋ ๊ฒ๋ฟ๋ง ์๋๋ผ, ์ ๋ณด๋ฅผ ๋ฐ์ ์ ์๋ค.
- ์ปค๋ฎค๋์ผ์ด์ ๊ณผ์ ์ ์ ์งํ๊ณ ๋ชจ๋ํฐ๋งํ๋ ์ 3์ ๊ฐ์ฒด (NotificationCenter ๊ฐ์ ์ธ๋ถ ๊ฐ์ฒด)๊ฐ ํ์ ์๋ค.
- ํ๋กํ ์ฝ์ด ์ปจํธ๋กค๋ฌ ๋ฒ์ ๋ด์์ ์ ์๋๋ค.
๋จ์
- ๋ง์ ์ฝ๋๊ฐ ํ์ํ๋ค.
- ํฌ๋์๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ delegate ์ค์ ์ nil์ด ๋ค์ด๊ฐ์ง ์๋๋ก ์ฃผ์ํด์ผํ๋ค.
- ๋ง์ ๊ฐ์ฒด๋ค์๊ฒ ์ด๋ฒคํธ๋ฅผ ์๋ฆฌ๋ ๊ฒ์ด ์ด๋ ต๊ณ ๋นํจ์จ์ ์ด๋ค.
- ์ํ ์ฐธ์กฐ๋ฅผ ๋ง๋ค์ด๋ผ ์๋ ์๊ธฐ ๋๋ฌธ์ delegate ํ๋กํผํฐ๋ฅผ weak๋ก ์ ์ธํ๊ธฐ๋ ํ๋ค.
2. Notification
- Notification Center๋ผ๋ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ํตํด ์ด๋ฒคํธ๋ค์ ๋ฐ์ ์ฌ๋ถ๋ฅผ ์ต์ ๋ฒ๋ฅผ ๋ฑ๋กํ ๊ฐ์ฒด๋ค์๊ฒ Notification์ postํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
- Notification์ NSNotification ํด๋์ค๋ก ๊ตฌํ๋์ด์๊ณ , Notification.Name์ด๋ผ๋ key ๊ฐ์ ํตํด ๋ณด๋ด๊ณ ๋ฐ์ ์ ์๋ค.
- UserInfo ๋์ ๋๋ฆฌ๋ฅผ ํตํด ์ฐ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ์ ๋ฌํ ์ ์๋ค.
- ๊ฐ์ฒด๋ค์ด ์ฃผ๊ณ ๋ฐ๋ ๋ฉ์์ง์ด๋ฏ๋ก, ์ฌ์ฉ์๋ค์๊ฒ ์๊ฐ์ ์ธ ์๋ฆผ์ ์ ๋ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ํ๊ฐ ์์ด ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์๋ค. (Authorization Not Required)
- Notification์ด post๋๋ฉด ์ฆ์ ํด๋น Notification์ ์ฒ๋ฆฌํ๋ ๋ชจ๋ Observer์๊ฒ ์ ๋ฌ๋๋ค. (Foreground, Background)
- ์ฃผ๋ก 1:N์ผ๋ก ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ ๋ ์ฌ์ฉํ๋ค.
ํฐํธ๋ฅผ ์ ํํ๊ณ ํฐํธ ์ ๋ณด๋ฅผ Notification์ผ๋ก ์ ๋ฌํ๋ TableViewController
Notification์ ํตํด ์ ํ๋ ํฐํธ ์ ๋ณด๋ฅผ ๋ณด๋ธ๋ค.
class SelectFontTableViewController: UITableViewController { func selectFont(theme: FontStyle) { if theme == .mapoFlowerIsland { Common.AppFontName.regular = "MapoFlowerIsland" } else if theme == .cafe24SurroundAir { Common.AppFontName.regular = "Cafe24SsurroundAir" } else if theme == .sdMisaeng { Common.AppFontName.regular = "SDMiSaeng" } // Notification DispatchQueue.global().async { NotificationCenter.default.post(name: NSNotification.Name.FontStyleDidChange, object: nil, userInfo: ["FontStyle": Common.AppFontName.regular]) } } override func viewDidLoad() { super.viewDidLoad() let fontStyle = Common.AppFontName.regular if fontStyle == "MapoFlowerIsland" { selectFont(theme: .mapoFlowerIsland) } else if fontStyle == "Cafe24SsurroundAir" { selectFont(theme: .cafe24SurroundAir) } else if fontStyle == "SDMiSaeng" { selectFont(theme: .sdMisaeng) } } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { switch indexPath.row { case 0: selectFont(theme: .mapoFlowerIsland) case 1: selectFont(theme: .cafe24SurroundAir) default: selectFont(theme: .sdMisaeng) } } }ํฐํธ ์ ๋ณด Notification์ ๋ฐ๋ ViewController
SelectFontViewController์์ ํฐํธ๊ฐ ์ ํ๋์ด์ ๋ณด๋ด๋ Notification์ FontPreviewController์์ ๊ตฌ๋ ํ๋ค.
class FontPreviewViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() fontTextView.font = UIFont(name: Common.AppFontName.regular, size: 14) // ์ต์ ๋ฒ๋ฅผ ํตํด ๊ตฌ๋ ํ๋ค. NotificationCenter.default.addObserver(self, selector: #selector(process(notification:)), name: Notification.Name.FontStyleDidChange, object: nil) } // ์ต์ ๋ฒ ํด์ deinit { NotificationCenter.default.removeObserver(self) } }์ฅ์
- ๋ง์ ์ค์ ์ฝ๋๊ฐ ํ์ ์์ด ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
- ๋ค์์ ๊ฐ์ฒด๋ค์๊ฒ ๋์์ ์ด๋ฒคํธ์ ๋ฐ์์ ์๋ ค์ค๋ค.
- Notification๊ณผ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ Any? ํ์ ์ object, [AnyHashable: Any]? ํ์ ์ userInfo๋ก ์ ๋ฌํ ์ ์๋ค.
๋จ์
- key ๊ฐ์ผ๋ก Notification์ ์ด๋ฆ๊ณผ userInfo๋ฅผ ์๋ก ๋ง์ถ๊ธฐ ๋๋ฌธ์ ์ปดํ์ผ ์ ๊ตฌ๋ ์ด ์ ๋๊ณ ์๋์ง, ์ฌ๋ฐ๋ฅด๊ฒ userInfo์ value๋ฅผ ๋ฐ์์ค๋์ง ์ฒดํฌํ ์ ์๋ค.
- ์ถ์ ์ด ์ด๋ ค์ธ ์ ์๋ค.
- Notification post ์ดํ ์ ๋ณด๋ฅผ ๋ฐ์ ์ ์๋ค.
3. Key Value Observing (KVO)
- A ๊ฐ์ฒด์์ B ๊ฐ์ฒด์ ํ๋กํผํฐ๊ฐ ๋ณํ๋จ์ ๊ฐ์งํ ์ ์๋ ํจํด
- ์์ ๋ ํจํด์ด ์ฃผ๋ก Controller์ ๋ค๋ฅธ ๊ฐ์ฒด ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ค๋ฃฌ๋ค๋ฉด KVO ํจํด์ ๊ฐ์ฒด์ ๊ฐ์ฒด ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ค๋ฃจ๋๋ฐ ์ ํฉํ๋ค.
- ๋ฉ์๋๋ ๋ค๋ฅธ ์ก์ ์์ ๋ํ๋๋ ๊ฒ์ด ์๋ ํ๋กํผํฐ์ ์ํ์ ๋ฐ์ํ๋ ํํ์ด๋ค
์ฅ์
- Model๊ณผ View์ ๊ฐ์ด ๋ ผ๋ฆฌ์ ์ผ๋ก ๋ถ๋ฆฌ๋ ํํธ ๊ฐ์ ๋ณ๊ฒฝ์ฌํญ์ ์ ๋ฌํ๋๋ฐ ์ ์ฉํ๋ค.
- ๋ ๊ฐ์ฒด ์ฌ์ด์ ์ ๋ณด๋ฅผ ๋ง์ถฐ์ฃผ๋ ๊ฒ์ด ์ฝ๋ค.
- new/old value๋ฅผ ์ฝ๊ฒ ์ป์ ์ ์๋ค.
- key path๋ก observingํ๊ธฐ ๋๋ฌธ์ nested objects ๋ํ observingํ ์ ์๋ค.
๋จ์
- NSObject๋ฅผ ์์๋ฐ๋ ๊ฐ์ฒด์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- deallocํ ๋ ์ต์ ๋ฒ๋ฅผ ์ง์์ค์ผํ๋ค.
- ๋ง์ value๋ฅผ ๊ฐ์งํ ๋์๋ ๋ง์ ์กฐ๊ฑด๋ฌธ์ด ํ์ํ๋ค.
- objc dynamic ์์ฑ์ ๋ถ์ฌ์ค์ผํ๋ค.
์ฐธ๊ณ ๋ฌธ์
Delegation, Notification, ๊ทธ๋ฆฌ๊ณ KVO
When to use Delegation, Notification, or Observation in iOS - Shine Solutions Group
'Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] Key Value Observing (KVO) (0) 2022.03.24 [Swift] Type Alias (typealias) (ํ์ ๋ณ์นญ ์ ์ธ) (0) 2022.03.23 [Swift] Copy On Write (COW) (0) 2022.03.03 [Swift] Access Control (์ ๊ทผ ์ ์ด) (0) 2022.02.28 [Swift] print ํจ์ (separator, terminator) (0) 2022.02.26