2020/05/17 - [iyOmSd/Title: Swift] - [Swift] Coordinator Pattern (1/2) - 기본원리
전게시글에서 Coordinator가 어떤 원리로 돌아가는지 느낌을 살펴봤구요
이제 써먹을 수 있도록(?) 구현해볼게요
제가 생각한 Coordinator는 Navigation을 각 하나씩 가지고있어요
따라서 어떤뷰를 present시킨다면 Navigation을 present하게 할거에요
(= Coordinator를 present)
왜냐하면 해당 Coordinator에서도 push이벤트가 발생할경우
NavigationController가 없다면 동작하지 않는다고 생각했기 때문이에요
그렇게하나면 Coordinator가 띄워질때 자신의 부모Coordinator도 알고 있어야겠죠?
이유는 아래에서 다시 언급할게요
이를토대로
Coordinator프로토콜을 한번 정의해볼께요
protocol Coordinator {
var parentCoordinateor: Coordinator? { get set }
var childCoordinators: [Coordinator] { get set }
var navigation: UINavigationController { get set }
func storyboardStart()
}
Class를 구현을 해볼까요..?
class MainCoordinator: Coordinator {
var parentCoordinateor: Coordinator?
var childCoordinators: [Coordinator] = []
var navigation: UINavigationController
init(parent: Coordinator?, navigation: UINavigationController) {
self.navigation = navigation
self.parentCoordinateor = parent
storyboardStart()
}
func storyboardStart() {
DispatchQueue.main.async {
let vc = ViewController()
vc.view.backgroundColor = .purple
vc.coordinator = self
self.navigation.pushViewController(vc, animated: false)
}
}
}
생성될 때
Navigation을 받아오고
부모Coordinator를 받아온뒤
스토리보드 혹은 코드로 기본화면이 될 VC를 띄워줬어요
여기서이제 추가적으로 뷰를 이동시키는 작업을 해야겠죠?
이벤트를 받을 Protocol을 구현하고 delegate패턴을 적용할거에요
protocol ViewControllerHandler: AnyObject {
func click(event: Event)
}
enum EventType {
case push
case pop
case present
case dismiss
}
click함수에 Event타입을 넣어주고
그 타입을 분기처리해서 전환을 처리를 할거에요
Coordinator에 프로토콜을 적용시키고
VC에 delegate를 넣어줄게요
class ViewController: UIViewController, Storyboarded {
weak var coordinator: MainCoordinator?
var delegate: ViewControllerHandler?
func movePush() {
delegate.click(event: .push)
}
}
이런식으로 push이벤트를 넘겨주면
ViewControllerHandler를 채택한 곳에서 이벤트가 발생하겟죠?
Coordinator가 뷰컨의 이벤트를 받아서 어느 화면으로 갈지 결정하도록 하면되요
아래는 간단하게 화면전환만 다뤘고 이런식으로 넘기는 로직을 구현하면되요
class MainCoordinator: Coordinator {
var parentCoordinateor: Coordinator?
var childCoordinators: [Coordinator] = []
var navigation: UINavigationController
init(parent: Coordinator?, navigation: UINavigationController) {
self.navigation = navigation
self.parentCoordinateor = parent
storyboardStart()
}
func storyboardStart() {
DispatchQueue.main.async {
let vc = ViewController()
vc.view.backgroundColor = .purple
vc.coordinator = self
vc.delegate = self
self.navigation.pushViewController(vc, animated: false)
}
}
}
extension MainCoordinator: ViewControllerHandler {
func click(event: Event) {
DispatchQueue.main.async {
switch event {
case .push:
let nextVC = ViewController()
nextVC.coordinator = self
nextVC.delegate = self
self.navigation.pushViewController(nextVC, animated: true)
case .present:
let navi = UINavigationController()
navi.modalPresentationStyle = .fullScreen
let childCoordinator = MainCoordinator(parent: self, navigation: navi)
self.childCoordinators.append(childCoordinator)
self.navigation.present(navi, animated: true)
case .pop:
self.navigation.popViewController(animated: true)
case .dismiss:
self.parentCoordinateor?.childCoordinators.removeLast()
self.navigation.dismiss(animated: true)
}
}
}
더 복잡한 로직을 구현하다보면
delegate 이벤트를 발생시키는데 동작을 안하는경우가 종종 있어요
그럴때는 아마도 delegate = self를 하면서 전달받다가
화면이 사라질경우 delegate또한 nil이 되기때문에 작동안하는 경우가 있더라구요
Class타입이기때문에 메모리관리도 신경쓰면서 구현해야할 필요가 있어요
'iyOmSd > Title: Swift' 카테고리의 다른 글
[Swift] Xcode release, debug app 구분하기 (0) | 2020.07.27 |
---|---|
[Swift] CAEmitterLayer, CAEmitterCell - 파티클 효과 (0) | 2020.06.20 |
[Swift] - Alamofire 5.1 변경된 통신 및 Json Dynamic Key (0) | 2020.05.18 |
[Swift] Coordinator Pattern (1/2) - 기본원리 (0) | 2020.05.17 |
[Swift] - JavaScriptCore(1/2) (0) | 2020.05.16 |