NotificationCenter

2023. 10. 24. 10:56Swift

320x100
Notification의 전달은, 알림을 만들어내는 Publisher, 이걸 전달하는 Dispatcher역할의 NotificationCenter, 그리고 그 알림을 관찰하는 Observer(혹은 Subscriber)의 관계를 통해 진행

Notification Dispatch

Dispatch = 어떤 것을 전송하는 역할을 담고 있는 것
  • DispatchQueue : 스레드에 어떠한 작업을 해달라고 보낼 것들의 Queue
  • Flux 패턴의 Dispatcher는 원하는 액션을 처리하기 위한 Reducer에게 그 액션을 보내는 역할

왜 Dispatch를 사용하는 것일까?

하나의 Dispatcher를 사용하면 데이터의 흐름을 한 점을 지나도록 만들 수 있다.

  • DispatchQueue, NotificationCenter는 시스템적인 기능을 이용하기 위해 도와줌
    ⇒ 관련 기능을 이미 구현해 가지고 있는 하나의 Dispatcher를 이용하는 것이 안전

Broadcast와 Observer의 역할

Broadcast

어떤 곳에서 이벤트가 일어났다, 조건이 충족되었다는 점을 다른 View, 혹은 ViewController에도 알리고 싶으면 Notification을 Broadcast해야 한다.

위에서 말한 것처럼 NotificationCenter는 Dispatcher의 역할을 하기 위해, 우리가 소식을 알려주면 앱 내부에서 그걸 방송해주는 역할

Observer

NotificationCenter에서 뿌려주는 정보도 Observer, 관찰자가 있어야 한다. 또한, 주파수를 맞추는 것마냥, 어떤 정보에 대해 관찰을 할 것인지도 정해야 한다. 많고 다양한 소식이 NotificationCenter로부터 쏟아져나올텐데, 이거에 다 하나하나 반응해줄 수는 없다.

이 NotificationCenter에는 특정 방송을 관찰, 구독할 수 있도록 돕는 메서드도 포함되어있다.

실제 코드에서의 쓰임

NotificationCenter.default. ...

싱글톤 패턴처럼 앱 전체적으로 하나의 객체에서 관리할 수 있도록 default가 정의되어 있음

  • 개발자가 굳이 만들지 않아도 앱마다 하나씩 돌아가고 있음

하지만 엄격한 싱글톤은 아니라서 자신의 필요에 따라 NotificationCenter를 더 정의해 사용할 수 있음

어떤 작업이 끝났을 때 알림을 보내는 경우

NotificationCenter.default.post(name: Notification.Name(name: "workCompleted"), object: nil)

default에 접근해서 post 메서드를 이용해 “workCompleted”라는 이름을 가진 Notification을 하나 생성해 넘긴다.

  • object를 이용하면 데이터도 원하는 데이터를 넘길 수 있음
  • 받는 쪽과 보내는 쪽이 서로 맞춰지도록 Notification.Name을 통해 이름을 맞춤
NotificationCenter.default.addObserver(forName: Notification.Name("workCompleted"),object: nil, queue: nil){ _ in
	// Handler ...
	print("Work Completed!")
}

받고자 할 때 addObserver를 이용하면 됨. forName에서는 받고자 하는 이름에 맞춰서 설정

  • 이미 시스템에서 설정된 알림들은 해당 정보를 가져와 사용하면 됨
  • ... forName: UIDevice.orientationDidChangeNotification, ...
NotificationCenter.default.addObserver(forName: Notification.Name("workCompleted"), object: nil, queue: nil) { notification in
	let str = notification.object as! String
	// ...
}

만약 post에서 어떤 값을 보냈다면 핸들러를 수정할 필요가 있음

  • 기존 코드의 핸들러 타입( _ )은 (Notification) -> Void 라서, Notification 객체가 들어온다고 생각하면 된다
  • 만약 보낸 데이터가 String인 경우 Notification의 객체의 object를 String으로 캐스팅해서 사용

실제 이용 코드

💡 Singleton에 생성되어있는 UIAlertAction을 터치하면 WebView로 넘어가기
//MyViewController.swift

import UIKit

...

class MyViewController: UIViewController{
	override viewDidLoad(){
		super.viewDidLoad
		NotificationCenter.default.addObserver(self,
        	selector: #selector(navigateToNextScreen),
			name: Notification.Name("NavigateToNextScreen"),
			object: nil
		)
	}
	deinit{
		NotificationCenter.default.removeObserver(self)
	}

	@objc func navigateToNextScreen() {
		if MemberManager.shared.account == 9{
			let storyboard = UIStoryboard(name: "MyWebViewController", bundle: nil)
			let vc = storyboard.instantiateViewController(withIdentifier: "MyWebViewController") as! MyWebViewController
    			vc.url = "www.naver.com"
    			self.navigationController?.pushViewController(vc, animated: true)
	}
  }
}
//MyWebViewController.swift
import UIKit
import WebKit

class MyWebViewController: UIViewController{
	@IBOutlet var webView: WKWebView!
	
	var url: String?

	override func viewDidLoad(){
		super.viewDidLoad()
		
		webView = WKWebView(frame: self.view.frame)
		self.view = webView
        
		let url = URL(string: url)
		let request = URLRequest(url: url!)
        
		webView.allowsBackForwardNavigationGestures = true // 뒤로가기 제스처 허용
        
		webView.configuration.preferences.javaScriptEnabled = true
        
		webView.load(request)
	}
}
//MeberManager.swift
import Foundation

...

class MemberManger: NSObject {
	static let shared = MemberManger()

	var accoun: Int

	...

	public func reselectButton(){
		let accountSelect = UIAlertController(title: "계정선택", message: "",
			preferredStyle: .alert)

		...

		let testAccount9 = UIAlertAction(title: "WebView", style: .default) { _ in
			self.account = 9
			NotificationCenter.default.post( name: Notification.Name("NavigateToNextScreen"), object: nil)
		}

		accountSelect.addAction(testAccount9)
		UIApplication.topViewController()?.present(accountSelect, animated: true)
	}
}
// UIApplicationExtention.swift
class func topViewController(base: UIViewController? = UIApplication.shared.windows[0].rootViewController) -> UIViewController? {
  if let nav = base as? UINavigationController {
	  return topViewController(base: nav.visibleViewController)
  }
  if let tab = base as? UITabBarController {
	  if let selected = tab.selectedViewController {
	    return topViewController(base: selected)
    }
  }
  if let presented = base?.presentedViewController {
	  return topViewController(base: presented)
  }
	return base
}

 


아래블로그를 참고하여 정리하였습니다.

 

Swift: NotificationCenter와 사용법

Notification과 NotificationCenter의 사용법을 알아보자

medium.com

 

[SWIFT] WebView 생성하기

안녕하세요 이번 포스팅에서는 Xcode 프로젝트에서 swift로 webView를 하나 만들어볼까 합니다 WKWebView WKWebView는 iOS dev 문서에 따르면 "인앱 브라우저와 같은 대화형 웹 콘텐츠를 표시하는 개체입니

jpointofviewntoe.tistory.com

 

728x90

'Swift' 카테고리의 다른 글

[문법] Codable  (0) 2023.08.18
[문법] 프로토콜  (0) 2023.08.15
[문법] Error  (0) 2023.08.14
[문법] inout  (0) 2023.08.14
[문법] Closure  (0) 2023.08.04