【问题标题】:Pushing to a new Viewcontroller from an inactive Viewcontroller (programatically)从非活动视图控制器推送到新视图控制器(以编程方式)
【发布时间】:2015-04-04 09:38:46
【问题描述】:

简短的解释。

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

ContainerViewController 有 2 个子 ViewController。 SlidePanelViewController(滑出式菜单)和CenterViewController(内容)

我的菜单中有一个“退出”按钮。单击此按钮时,我想将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 中)来检查该函数是否有效。它完全符合我的要求。

但是,当我从菜单中调用此函数时(同样,我的菜单是 childViewControllerContainerViewController)。它不起作用。

我试图这样称呼它:

ContainerViewController().signOut()

我还尝试将Delegate 添加到我的SidePanelViewController,如下所示:

课前:

@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 上课之前:

var leftViewController: SidePanelViewController?

我的ContainerViewController 班级:

class ContainerViewController: UIViewController, CenterViewControllerDelegate, SidePanelViewControllerDelegate, UIGestureRecognizerDelegate {

在我的ContainerViewController'sviewDidLoad()

leftViewController?.delegate = self

我将ContainerViewController 类中的signOut 函数更改为:

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

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

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

【问题讨论】:

标签: ios swift uiviewcontroller menu uicontainerview


【解决方案1】:

您正在尝试使用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()
    }
}

希望对您有所帮助。

【讨论】:

  • 试过self.signOut(),但会导致以下错误:'SidePanelViewController' does not have a member named 'signOut'
  • 我将更新我的答案以响应委托位。
  • 我建议使用println 来检查myButtonWasPressed 是否被调用。如果如果被调用,您应该使用println 来检查delegate 不是nil
  • 嗯,很有趣...好吧,看不到您的代码会使这有点困难。你如何设置你的SidePanelViewController。问题是代理设置不正确......
  • 检查,当您使用leftViewController?.delegate = self 时,leftViewController 不为零。这将导致委托保持为零。
【解决方案2】:

问题似乎是 navigationController 是 nil 并且您正试图强制打开它(如您的错误所示)。

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

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

如果您使用的是故事板

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

当您在故事板上时:

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

如果您不使用情节提要

看看这个帖子:Programatically creating UINavigationController in iOS

【讨论】:

  • 我没有使用故事板。因此推送到 navigationStack 而不是简单地使用 segue。如何以编程方式嵌入导航控制器?
猜你喜欢
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 2021-02-03
  • 2020-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多