从不活动的 Viewcontroller 推送到新的 Viewcontroller(以编程方式)

Pushing to a new Viewcontroller from an inactive Viewcontroller (programatically)

简短说明。

我有一个 ContainerViewController 正在推送到 navigationStack。

ContainerViewController 有 2 个子视图控制器。一个 SlidePanelViewController(滑出式菜单)和一个 CenterViewController(内容)

我的菜单中有一个 "sign Out" 按钮。单击此按钮后,我想将 ContainerViewController(它是 2 childViewControllers)推送到我的 LandingPageViewController.

这是我要调用的函数:

func signOut() {
println("signOut")


// Set up the landing page as the main viewcontroller again.
let mainTableViewController = LandingPageVC()
mainTableViewController.navigationItem.setHidesBackButton(true, animated: false)
mainTableViewController.skipView = false
self.navigationController!.pushViewController(mainTableViewController, animated: true)

// Disable menu access
menuEnabled = false

// change status bar style back to default (black)
UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.Default
}

起初我试着把它放在我的 SlidePanelViewController 里。那没有用。所以我把它放在我假设它属于 ContainerViewController.

的地方

但是,当我在菜单中单击 signOutButton 时。我遇到了错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

查看错误时。这是导致它的行:

self.navigationController!.pushViewController(mainTableViewController, animated: true)

错误发生后,我通过添加调用该函数的 UINavigationBarButtonItem(在我的 ContainerViewController 中)来检查该函数是否有效。它完全符合我的要求。

然而,当我从我的菜单中调用这个函数时(同样我的菜单是 ContainerViewControllerchildViewController)。它不起作用。

我试着这样称呼它:

ContainerViewController().signOut()

我也试过在我的 SidePanelViewController 中添加一个 Delegate,像这样:

在class之前:

@objc protocol SidePanelViewControllerDelegate {
    optional func needsSignOut(sender: SidePanelViewController)
    optional func toggleLeftPanel()
    optional func collapseSidePanels()
}

viewDidLoad()中:

//  Make sure your delegate is weak because if a ContainerViewController owns
//  a reference to a SidePanelViewController and the container view controller
//  is its delegate, you'll end up with a strong reference cycle!
weak var delegate: SidePanelViewControllerDelegate?

在我的点击手势功能中:

func signOutTapGesture() {
    println("signOutTapGesture")
    selectView(signOutView)

    delegate?.needsSignOut?(self)
    println(delegate)
}

在我的ContainerViewController之前class:

var leftViewController: SidePanelViewController?

我的ContainerViewControllerclass:

class ContainerViewController: UIViewController, CenterViewControllerDelegate, SidePanelViewControllerDelegate, UIGestureRecognizerDelegate {

在我的ContainerViewController'sviewDidLoad()

leftViewController?.delegate = self

然后我将 ContainerViewController class 中的 signOut 函数更改为:

func needsSignOut(sender: SidePanelViewController) {
    println("needsSignOut called")
    self.signOut()
}

但是像上面那样使用委托,似乎也没有做任何事情。

任何关于如何从菜单中成功推送我的 LandingPageVC 的帮助将不胜感激! (我没有使用故事板)

问题似乎是 navigationController 为 nil 而您试图强制解包(如您的错误所示)。

我在另一个答案中讨论过的一个问题。

另一个问题可能是您没有添加导航控制器。为此,您需要:

如果您使用的是故事板

您需要确保已嵌入 UINavigationController。之后,当您使用 navigationController 时,它不会为零,您将能够推送您的视图控制器。

当你在故事板上时:

此外,如果您使用故事板,您是否考虑过使用 segues 来移动而不是调用 presentViewController?我发现它让一切变得更容易。

如果您没有使用故事板

看看这个post:Programatically creating UINavigationController in iOS

您正试图用 ContainerViewController().signOut() 呼叫 signOut。这将创建一个新的 ContainerViewController,因为您还没有将它压入导航控制器的堆栈,所以 navigationController 为零。尝试只调用 self.signOut()。 (我假设 signOut 的方法是 ContainerViewController

更新 - 代表

您的代表 属性 应该进入 SidePanelViewController。我会给你和如何实现它的例子:

侧面板视图控制器: (注意 - 协议不必放在此处,但我认为它可以使事情井井有条)

@objc protocol SidePanelViewControllerDelegate {
    optional func needsSignOut(sender: SidePanelViewController)
}

class SidePanelViewController: UIViewController {
    //  Make sure your delegate is weak because if a ContainerViewController owns
    //  a reference to a SidePanelViewController and the container view controller
    //  is its delegate, you'll end up with a strong reference cycle!
    weak var delegate: SidePanelViewControllerDelegate?

    //  Called when the UIButton is pressed.
    func myButtonWasPressed() {
        delegate?.needsSignOut?(self)
    }
}

容器视图控制器:

class ContainerViewController: UIViewController {
    var sidePanel: SidePanelViewController!
    // Setup the side panel...

    override func viewDidLoad() {
        super.viewDidLoad()
        sidePanel.delegate = self
    }

    func signOut() {
        // Sign out stuff here.
    }
}

//  The ContainerViewController needs to conform to the SidePanelViewControllerDelegate
//  protocol if we want the delegate to work. (This could have gone in the initial
//  class declaration.)
extension ContainerViewController : SidePanelViewControllerDelegate {
    func needsSignOut(sender: SidePanelViewController) {
        self.signOut()
    }
}

希望对您有所帮助。