我正在使用SpriteKit为iOS制作游戏。

我有2个Viewcontrollers。一个是GameViewController,另一个是MenuViewController。我们分别称它们为A和B。

当玩家死亡时,会在GameScene.swift中调用一个函数,该函数向B启动模式“迷失” Segue。玩家可以在此处重新开始游戏或购买生命,并向A调用“ Back” Segue。

我需要取消每次调用segue时创建的其他视图。

问题是:我需要“ Lost” Segue将有关得分的数据发送到视图B,并且我需要“ Back” Segue将数据发送到View A,以了解玩家是否使用了生命。

我已经实现了所有这些。但是现在我需要找到如何消除旧的视图,这些视图会继续占用设备的内存,从而导致延迟和崩溃。

我已经搜索了几个小时。没有解决方案适合我的情况。

我找到的解决方案要么导致我的应用程序出现错误,要么不传递数据,要么不生成视图。

因为有很多,我不会在这里添加代码。但是我敢肯定,答案确实很简单,只是对于像我这样的初学者而言并非如此。

我认为可能的解决方案是从B到A轻松进行选择?

但是,轻松的搜寻是否传递数据?

而且,我没有找到关于如何使用放松顺序的答案。

我用尽了所有的可能性。堆栈交换是我最后的机会。

最佳答案

您绝对应该使用放松的顺序来返回到先前的viewController,否则,因为发现内存使用量增加,直到应用程序退出为止。

我根据您的描述创建了以下示例。它使用标准序列从GameViewController移至MenuViewController,并使用展开序列从MenuViewController移回到GameViewController。

GameViewController具有玩家骰子UIButton,用于输入分数的UITextField和用于显示生活的UILabel

MenuViewController具有用于显示分数的UILabel,用于添加生命的Buy Life(购买生命)UIButton和用于返回GameViewController的Restart UIButton

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP

这是代码:

GameViewController.swift

import UIKit

class GameViewController: UIViewController {

    @IBOutlet weak var scoreTextField: UITextField!
    @IBOutlet weak var livesLabel: UILabel!

    var lives = 3

    func updateLivesLabel() {
        livesLabel.text = "Lives: \(lives)"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        updateLivesLabel()
    }

    // This is the function that the unwind segue returns to.
    // You can call it anything you want, but it has to be in
    // the viewController you are returning to, it must be tagged
    // with @IBAction and it must take a UIStoryboardSegue as its
    // only parameter.
    @IBAction func returnFromMenu(segue: UIStoryboardSegue) {
        print("We're back in GameViewController")

        // Update the lives label based upon the value passed in
        // prepareForSegue from the MenuViewController.
        updateLivesLabel()
    }

    @IBAction func goPlayerDies(sender: UIButton) {
        lives--
        self.performSegueWithIdentifier("Lost", sender: self)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "Lost" {
            let destinationVC = segue.destinationViewController as! MenuViewController
            destinationVC.score = Int(scoreTextField.text ?? "") ?? 0
            destinationVC.lives = lives
        }
    }
}


MenuViewController.swift

import UIKit

class MenuViewController: UIViewController {

    @IBOutlet weak var scoreLabel: UILabel!

    var score = 0
    var lives = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        scoreLabel.text = "Score: \(score)"
    }

    @IBAction func buyLife(sender: UIButton) {
        lives++
    }

    @IBAction func goRestart(sender: UIButton) {
        self.performSegueWithIdentifier("Back", sender: self)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "Back" {
            let destinationVC = segue.destinationViewController as! GameViewController
            destinationVC.lives = lives
        }
    }
}




这是连接正向序列以编程方式调用的方式:

按住Control键从ViewController图标拖动到MenuViewController:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



从弹出窗口中选择“模态呈现”:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



单击viewControllers之间的segue箭头,并在Attributes Inspector中为其指定标识符:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



这是您如何以编程方式将展开的序列连接起来的方法:

按住Control键从ViewController图标拖动到Exit图标:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



从弹出菜单中选择returnFromMenu:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



单击“文档大纲”中的“展开”,然后在右侧的“属性”检查器中为其指定标识符“后退”:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



替代答案

您可以手动显示和关闭viewController,而不是使用segues。您的应用程序的优点是MenuViewController将仅分配一次,并且在应用程序的生命周期内将持续存在。相同的viewController将被反复显示和关闭,但是不会被释放,我怀疑这会导致您的崩溃。

GameViewController将是由Storyboard创建的initialViewController。 MenuViewController将被加载到GameViewController的viewDidLoad中。

为了使这项工作有效,您需要向MenuViewController添加一个标识符,以便可以通过名称实例化它。单击情节提要中的MenuViewController,然后在身份检查器中设置其情节提要ID:

swift - 在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A-LMLPHP



这是代码。请注意,所有关于segue的提及都已消失。注意如何使用viewWillAppear更新viewControllers。

GameViewController.swift

import UIKit

class GameViewController: UIViewController {

    @IBOutlet weak var scoreTextField: UITextField!
    @IBOutlet weak var livesLabel: UILabel!

    var menuViewController: MenuViewController?

    var lives = 3

    func updateLivesLabel() {
        livesLabel.text = "Lives: \(lives)"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        menuViewController = self.storyboard!.instantiateViewControllerWithIdentifier("MenuViewController") as? MenuViewController
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        updateLivesLabel()
    }

    @IBAction func goPlayerDies(sender: UIButton) {
        lives--
        menuViewController?.score = Int(scoreTextField.text ?? "") ?? 0
        menuViewController?.lives = lives
        self.presentViewController(menuViewController!, animated: true, completion: nil)
    }

}


MenuViewController.swift

import UIKit

class MenuViewController: UIViewController {

    @IBOutlet weak var scoreLabel: UILabel!

    var score = 0
    var lives = 0

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        scoreLabel.text = "Score: \(score)"
    }

    @IBAction func buyLife(sender: UIButton) {
        lives++
    }

    @IBAction func goRestart(sender: UIButton) {
        let destinationVC = self.presentingViewController as! GameViewController
        destinationVC.lives = lives
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    }
}

07-28 04:20