티스토리 뷰

화면 전환에서 현재 뷰를 dismiss 혹은 navigationViewController에서 pop 한 후 다른 뷰를 present 혹은 push 하는 부분에서
막혔던 과정을 포스팅해보겠습니다.

현재 뷰의 계층 상태는 rootView 와 각 각 다른 정보와 기능을 다루는 2개의 뷰로 이루어져 있습니다.
편의상 rootView, childView1, childView2 로 부르겠습니다.

rootView에서 childView1을 불러오고
childView1 에서의 작업을 끝내고 childView2로 넘어가려고 합니다.
childView1은 더 이상 남아있을 필요가 없기때문에 childView2로 가기전 childView1을 없애주고 넘어가려고 합니다.

떠오른 생각은 'childView1를 종료하고 completion을 이용해 childView2 를 불러오면 되겠구나' 였습니다.

 

그리고 작성한 코드는,

import UIKit

class ChildVC1: UIViewController {
	func showChildVC2 {
    	self.dismiss(animated: false, completion: {	
            let childVC2 = self.storyboard?.instantiateViewController(identifier: "childVC2") as! ChildVC2
            childVC2.modalPresentationStyle = .fullScreen
            self.present(childVC2, animated: true, completion: nil)
         })
    }
}

 

하지만 이 방법은 작동하지 않았습니다. 

그 이유는 마지막 줄의 self.present... 때문인데 

childVC1을 dismiss 한 후에는 더이상 childVC1이 view 상에 존재하지 않기 때문에 self 는 없는 값을 불러오게 됩니다.

 

그리고 여러시도 끝에 찾아 낸 방법은,

import UIKit

class ChildVC1: UIViewController {
	func showChildVC2 {
    	let rootView = presentingViewController
        
    	self.dismiss(animated: false, completion: {	
            let childVC2 = self.storyboard?.instantiateViewController(identifier: "childVC2") as! ChildVC2
            childVC2.modalPresentationStyle = .fullScreen
            rootView?.present(childVC2, animated: true, completion: nil)
         })
    }
}

presentingViewController 는 chilidView1 을 불러온 뷰 즉 rootView 를 가리킵니다.

rootView는 childVIew1 이 불러와지기 전부터 존재했고 childView1이 사라지더라도 뷰에서 제거하지 않는 이상 존재합니다.

 

이 방법을 통해 일반 뷰에서는 해결이 되었습니다.

하지만 제 프로젝트에서는 navigationViewContorller에서는 위 방법이 작동하지 않았고

다른 방법이 필요했습니다.

 

먼저 Swift 자체에는 navigationViewController push 와 pop 의 completion handler 기능이 없기 때문에 extension을 통해 이기능을 추가 해줍니다.

 

extension UINavigationController {
    func popViewController(animated: Bool, completion:@escaping (()->())) -> UIViewController? {
        CATransaction.setCompletionBlock(completion)
        CATransaction.begin()
        let poppedViewController = self.popViewController(animated: animated)
        CATransaction.commit()
        return poppedViewController
    }
    
    func pushViewController(_ viewController: UIViewController, animated: Bool, completion:@escaping (()->())) {
        CATransaction.setCompletionBlock(completion)
        CATransaction.begin()
        self.pushViewController(viewController, animated: animated)
        CATransaction.commit()
    }
}

 

그리고 rootView에서 childView1으로 화면이 전환될 때 childView1에 rootView 자신의 객체를 저장해 줍니다.

사용한 코드로는,

import UIKit

class RootView: UIViewController {
	func showChildVC1() {
    	let childVC1 = self.storyboard?.instantiateViewController(identifier: "childVC1") as! ChildVC1
        childVC1.rootView = self
        self.navigationController?.pushViewController(childVC1, animated: true)
    }
}


class ChildVC1: UIViewController {
	var rootView: RootView?
    
	func showChildVC2 {
    	self.navigationController?.popViewController(animated: true, completion: {
            let childVC2 = self.storyboard?.instantiateViewController(identifier: "childVC2") as! ChildVC2
            
            self.rootView?.navigationController?.pushViewController(childVC2, animated: true)
        })
    }
}

 

입니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함