0

컨테이너보기에서 childviewController에서 표시 한 모달 뷰를 닫는 데 문제가 있습니다. rootViewController (MainNavigationController)로 UINavigationController가 있고 selectedSegmentIndex 1 (secondViewController)의 childViewControllers 중 하나에서 모달을 표시합니다. 모달은 괜찮 았지만, 두 번째 ViewController (HomeController의 하위 클래스)로 돌아가려면 모달을 닫을 때 selectedIndex 0으로 다시 돌아옵니다. 따라서 selectedIndex 1 childViewController가 표시되지 않았습니다. 나는 모달을 닫고 사용자가 두 번째 ViewController에서 표시 한 childViewController로 돌아가서 selectedIndex 0으로 돌아 오지 않기를 바란다. 미리 감사드립니다!모달을 모덜 변환하고 containerView에 childViewController를 반환하십시오.

// NavigationConroller 같은 rootViewController

class MainNavigationController: UINavigationController { 

    var segmentedController: UISegmentedControl! 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 

     let vc1 = TravelersFeedVC() 
     let vc2 = ProfileVC() 

     if isLoggedIn() { 
      // assume user is logged in 
      let homeController = HomeController() 
      viewControllers = [homeController] 
      homeController.firstViewController = vc1 
      homeController.secondViewController = vc2 

     } else { 
      perform(#selector(showLoginController), with: nil, afterDelay: 0.01) 
     } 
    } 

    fileprivate func isLoggedIn() -> Bool { 
     return UserDefaults.standard.isLoggedIn() 
    } 

    func showLoginController() { 
     let loginController = LoginController() 
     present(loginController, animated: true, completion: { 
      // perhaps do something here later 
     }) 
    } 
} 

// HomeController 같은 parentViewController

class HomeController: UIViewController, FBSDKLoginButtonDelegate { 

    // child view controllers to put inside content view 
    var firstViewController: TravelersFeedVC? 
    var secondViewController: ProfileVC? 

    private var activeViewController: UIViewController? { 
     didSet { 
      removeInactiveViewController(inactiveViewController: oldValue) 
      updateActiveViewController() 
     } 
    } 

    private func removeInactiveViewController(inactiveViewController: UIViewController?) { 
     if let inActiveVC = inactiveViewController { 
      // call before removing child view controller's view from hierarchy 
      inActiveVC.willMove(toParentViewController: nil) 

      inActiveVC.view.removeFromSuperview() 

      // call after removing child view controller's view from hierarchy 
      inActiveVC.removeFromParentViewController() 
     } 
    } 

    private func updateActiveViewController() { 
     if let activeVC = activeViewController { 
      // call before adding child view controller's view as subview 
      addChildViewController(activeVC) 

      activeVC.view.frame = contentView.bounds 
      contentView.addSubview(activeVC.view) 

      // call before adding child view controller's view as subview 
      activeVC.didMove(toParentViewController: self) 
     } 
    } 

    // UI elements 
    lazy var contentView: UIView = { 
     let tv = UIView() 
     tv.backgroundColor = UIColor.purple 
     tv.translatesAutoresizingMaskIntoConstraints = false 
     tv.layer.masksToBounds = true 
     return tv 
    }() 


    var segmentedController: UISegmentedControl! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     activeViewController = firstViewController 

     checkIfUserIsLoggedIn() 

     view.addSubview(contentView) 

     setupProfileScreen() 

     let items = ["Travelers", "Me"] 
     segmentedController = UISegmentedControl(items: items) 
     navigationItem.titleView = segmentedController 

     segmentedController.tintColor = UIColor.black 
     segmentedController.selectedSegmentIndex = 0 

     // Add function to handle Value Changed events 
     segmentedController.addTarget(self, action: #selector(HomeController.segmentedValueChanged(_:)), for: .valueChanged) 

     navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(handleSignOut)) 
     navigationItem.leftBarButtonItem?.tintColor = UIColor.black 

    } 


    // reference to collectionViewController 
    var travelersFeedVC: TravelersFeedVC! 

    func segmentedValueChanged(_ sender:UISegmentedControl!) 
    { 
     switch segmentedController.selectedSegmentIndex { 
     case 0: 
      activeViewController = firstViewController 

     case 1: 
      activeViewController = secondViewController 

     default: // Do nothing 
      break 
     } 
    } 

// 모달가

class ProfileVC: UIViewController { 

// button to present modal 
    lazy var placesButton: UIButton = { 
     let customButton = UIButton(type: .system) 
     customButton.backgroundColor = UIColor.clear 
//  customButton.frame = CGRect(x: 150, y: 50, width: 120, height: self.view.frame.height) 
     customButton.setTitle("## of Places", for: .normal) 
     customButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16) 
     customButton.setTitleColor(.white, for: .normal) 
     customButton.addTarget(self, action: #selector(handleShowPlacesVC), for: .touchUpInside) 

     return customButton 
    }() 

// function to call to present modal 
    func handleShowPlacesVC() { 
     let placesVC = PlacesTableVC() 
     let navigationController = UINavigationController(rootViewController: placesVC) 
     present(navigationController, animated: true, completion: nil) 
    } 

// 모달 관점에서 제시 containerView에 secondViewcontroller 해제

override func viewDidLoad() { 
     super.viewDidLoad() 

     navigationItem.leftBarButtonItem = UIBarButtonItem(title: "back", style: .plain, target: self, action: #selector(handleCancel)) 

    } 

// dismiss modal view to return to secondViewController in childViewController containerView 
    func handleCancel() { 
     dismiss(animated: true, completion: nil) 
    } 
+0

왜 'MainNavigationController'에 세분화 된 컨트롤이 있습니까? – sooper

답변

0

모달 대화 상자를 닫으면 MainNavigationController의 viewDidAppear 함수가 호출됩니다. 거기에 차일드와 함께 새로운 homeController를 설정했다. 이것은 firstViewController의 설정으로 HomeController의 viewDidload를 트리거합니다. 거기에 중단 점을 설정하려고하면 볼 수 있습니다.

viewDidAppear에서 콘텐츠가 생성되지 않도록하려면 대신 viewDidLoad를 사용하는 것이 좋습니다.

또 다른 힌트 : 'dismiss'는 '보기 컨트롤러에 의해 모달로 표시된보기 컨트롤러를 닫습니다.'로 정의됩니다. - 예를 들어 모달 vc 위의 경고를 열면 모달보기가 아닌 경고가 닫힙니다 (자체). 올바르게 구현하면 현재 컨트롤러 (열어 본 컨트롤러)에서 해제를 호출해야합니다. "presentingViewController? .dismiss()" 사과는 아무 것도 표시되지 않은 경우에 대한 대체 기능을 구현했기 때문에 코드에서 작동하지만 언젠가 두통을 일으키는 함정.

+0

해결 방법으로 인한 후속 작업 대신이 문제를 올바르게 해결해야합니다. viewDidAppear은 뷰가 다시 나타날 때마다 호출됩니다. 앱을 백그라운드로 이동하고 예를 들어 포 그라운드로 돌아가서 해당 메소드를 호출합니다.이 경우 뷰 계층 구조를 조작하는 것이 올바르지는 않습니다. – ObjectAlchemist

+0

통찰력에 감사드립니다. 그것에 작동합니다. – user3708224

+0

그래서 viewDidLoad를 사용할 때 처음으로 앱에 로그인 할 때 빈 화면을 해결하는 방법을 알아낼 수 없습니다. viewDidLoad는 내 탐색 문제를 해결했지만 지금은 처음으로 로그인 할 때 빈 화면이 나타납니다 ... 방향에 대한 제안이 있습니까? – user3708224

0

자식보기 컨트롤러에서 present을 호출하더라도 실제로는 프레젠테이션을 처리하지 않을 가능성이 있습니다. Apple docs에서 :

이 메서드를 호출하는 개체는 항상 프레젠테이션을 처리하는 개체가 아닐 수도 있습니다. 각 프레젠테이션 스타일에는 동작을 관리하는 다른 규칙이 있습니다. 예를 들어 전체 화면 프리젠 테이션 자체가 전체 화면을 다루는보기 컨트롤러에 의해 만들어 져야합니다. 현재보기 컨트롤러가 요청을 수행 할 수없는 경우보기 컨트롤러 계층 구조 위로 요청을 가장 가까운 부모에게 전달하고 요청을 처리하거나 전달할 수 있습니다.

활성보기 컨트롤러에 대한 참조를 유지하기 때문에 해지시 명시 적으로 색인을 설정할 수 있습니다.