UINavigationController最多只能处理4个Viewcontrollers吗?

时间:2016-03-27 19:40:16

标签: ios swift uinavigationcontroller

我正在尝试在Xcode 7.x中构建一个故事板,其中包含超过4个嵌入在UINavigationController中的连续视图控制器。 导航控制器是初始视图控制器。 Embedded是一个简单的视图控制器,只包含一个按钮,它连接到Adaptive Show Segue,调用类似的视图控制器等等。每个人通过简单的Show Segue呼叫下一个。 Push仅适用于3个连续呼叫,此后对导航控制器的引用将丢失。 第5个视图控制器和打开以模态显示。

至少从iOS 8开始,我在不同的项目中遇到了这个问题。

UINavigationController viewControllers堆栈是否限制为4个条目?

More than 4 view controllers embedded in an UINavigationController

嵌入式视图控制器的代码:

class ViewController: UIViewController {

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

        print("ViewCintroller:\(title) NavController:\(navigationController) stack size:\(navigationController?.viewControllers.count)")
        print()
    }
}

输出:

ViewController:Optional("V1") NavController:Optional(<UINavigationController: 0x7fd57b024200>) stack size:Optional(1)
ViewController:Optional("V2") NavController:Optional(<UINavigationController: 0x7fd57b024200>) stack size:Optional(2)
ViewController:Optional("V3") NavController:Optional(<UINavigationController: 0x7fd57b024200>) stack size:Optional(3)
ViewController:Optional("V4") NavController:Optional(<UINavigationController: 0x7fd57b024200>) stack size:Optional(4)
ViewController:Optional("V5") NavController:nil stack size:nil
ViewController:Optional("V6") NavController:nil stack size:nil

将所有segue更改为已弃用的推送类型会导致所需的结果:

ViewController:Optional("V1") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(1)
ViewController:Optional("V2") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(2)
ViewController:Optional("V3") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(3)
ViewController:Optional("V4") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(4)
ViewController:Optional("V5") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(5)
ViewController:Optional("V6") NavController:Optional(<UINavigationController: 0x7fc8a1026200>) stack size:Optional(6)

编辑:

在我看来,问题在于界面构建器。 我有一个工作解决方案,改变所有显示segues推送segues,编译,改变push segues返回显示segues,再次编译和异常消失。导航堆栈不再受限于4个视图控制器。

1 个答案:

答案 0 :(得分:2)

  

每个人通过简单的Show Segue呼叫下一个。 Push仅适用于3个连续呼叫,此后对导航控制器的引用将丢失。 第5个视图控制器和on以模态显示。

我已经从你的问题中强调了这句话。

以模态方式呈现的视图控制器将为其nil属性返回navigationController,因为它未嵌入导航控制器中。如果你继续使用Show seque而不是modal来呈现第5个,第6个等等,你将继续看到导航控制器不是nil并且导航堆栈会继续增加(直到设备内存不足)。

除了可用的设备内存外,可以添加到导航控制器导航堆栈的视图控制器数量没有限制。

以模态方式呈现视图控制器不会将其添加到导航控制器的导航堆栈中。模态呈现的视图控制器将为其nil属性返回navigationController,因为它未嵌入导航堆栈中。

考虑以下示例:

enter image description here

我创建了这个NextViewController类。视图控制器只有&#34;添加另一个&#34;按钮,它连接到showAnother方法。此方法实例化另一个NextViewController并将其推送到堆栈。在viewWillAppear中,我正在记录您在prepareForSegue方法中记录的相同内容。

我可以不断点击&#34;添加另一个&#34;我想要多次,并且我将继续将另一个视图控制器添加到导航堆栈中,您可以从日志消息中看到,堆栈中的视图控制器数量正在增加以外四强。 (截图中的27)。这会消耗内存,最终我会耗尽,是的。

这里是NextViewController类的纯文本代码:

import UIKit

class NextViewController: UIViewController {
    init() {
        super.init(nibName: "NextViewController", bundle: NSBundle.mainBundle())
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        print("ViewCintroller:\(title) NavController:\(navigationController) stack size:\(navigationController?.viewControllers.count)")
    }

    @IBAction func showAnother() {
        navigationController?.pushViewController(NextViewController(), animated: true)
    }
}

为了完成起见,我添加了第二个按钮,它以NextViewController为根视图控制器实例化一个新的导航控制器。

当我点击蓝色按钮时,同样的事情发生在早期。我们将另一个NextViewController添加到当前导航堆栈并计数递增。当我们点击橙色时,我们正在查看新的堆栈(请注意导航控制器的内存地址现在不同)并且计数重置为1。

enter image description here

以下是该屏幕截图中的代码:

import UIKit

class NextViewController: UIViewController {
    init() {
        super.init(nibName: "NextViewController", bundle: NSBundle.mainBundle())
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        print("ViewCintroller:\(title) NavController:\(navigationController) stack size:\(navigationController?.viewControllers.count)")
    }

    @IBAction func showAnother() {
        navigationController?.pushViewController(NextViewController(), animated: true)
    }

    @IBAction func presentModally() {
        let anotherNavigationStack = UINavigationController(rootViewController: NextViewController())
        presentViewController(anotherNavigationStack, animated: true, completion: nil)
    }
}

这里注意蓝色&#34;添加另一个&#34;按钮连接到showAnother()和橙色&#34;呈现模态&#34;按钮连接到presentModally()

以下是日志中的示例:

ViewCintroller:nil NavController:Optional(<UINavigationController: 0x7fa889810800>) stack size:Optional(8)
ViewCintroller:nil NavController:Optional(<UINavigationController: 0x7fa88c057a00>) stack size:Optional(1)
ViewCintroller:nil NavController:Optional(<UINavigationController: 0x7fa88c057a00>) stack size:Optional(2)
ViewCintroller:nil NavController:Optional(<UINavigationController: 0x7fa88c057a00>) stack size:Optional(3)
ViewCintroller:nil NavController:Optional(<UINavigationController: 0x7fa88c042800>) stack size:Optional(1)

这些日志中的第一行表示连续第8次点击蓝色按钮。第2行表示已点击橙色按钮。请注意,内存地址从0x7fa889810800更改为0x7fa88c057a00。第3行和第4行表示蓝色按钮上的水龙头。我们注意到内存地址保持0x7fa88c057a00,但导航计数最多增加到3(代表一个橙色点击,然后是两个蓝色点击)。然后,对于第5行,我们点击了橙色按钮,内存地址再次从0x7fa88c057a00更改为0x7fa88c042800,并且计数再次重置为1.