在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A [英] Need to free memory after Modal Segues, but I need both my Segues to pass data from A to B and B to A

查看:54
本文介绍了在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用SpriteKit为iOS开发游戏.

I am making a game for iOS with SpriteKit.

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

I have 2 Viewcontrollers. One is the GameViewController and the other one is the MenuViewController. Let's call them A and B respectively.

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

When the player dies, a function is called in GameScene.swift that launches a modal "Lost" Segue to B. There, the player can restart the game or buy a life and a "Back" Segue is called to A.

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

I need to dismiss the additional Views that get created each time I call a segue.

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

Problem is: I need the "Lost" Segue to send data about the Score to View B and I need the "Back" Segue to send data to View A about wether or not the player used a life.

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

I have implemented all this. But now I need to find how to dismiss old views that keep eating the device's memory, thus leading to lag and crash.

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

I have googled for hours and hours. No solution was adapted to my situation.

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

The solutions I found either caused my app to bug, data not to be passed or views not to be generated.

由于有很多,我不会在这里添加代码.但是我敢肯定,答案确实很简单,只是对于像我这样的初学者来说不是.

I will not add code here since there is a LOT. But I am sure the answer is actually really easy, just not for a beginner like me.

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

I think a possible solution would be an unwind segue from B to A ?

但是放宽搜索是否沿着数据传递数据?

But do unwind segues pass data along ?

此外,我没有找到关于如何使用放松顺序的答案.

Moreover, I found no answer I could understand on how to use an unwind segue.

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

I exhausted all my possibilities. Stack Exchange is my last chance.

推荐答案

您绝对应该使用 unwind segue 返回先前的viewController,否则,因为发现内存使用量增加,直到您的应用程序退出.

You definitely should use an unwind segue to return to the previous viewController, otherwise as you have found your memory usage increases until your apps quits.

我根据您的描述创建了以下示例.它使用标准的segue从 GameViewController 移至 MenuViewController ,并使用 unwind segue MenuViewController strong>返回 GameViewController .

I created the following example from your description. It uses a standard segue to move from the GameViewController to the MenuViewController and it uses an unwind segue to move from the MenuViewController back to the GameViewController.

GameViewController 具有 Player Dies UIButton,用于输入得分的UITextField和用于显示生活的UILabel.

The GameViewController has a Player Dies UIButton, a UITextField for entering a score, and a UILabel for displaying the lives.

MenuViewController 具有用于显示乐谱的UILabel,用于购买生命的购买生活 UIButton和用于重新开始生活的重新启动 UIButton返回 GameViewController .

The MenuViewController has a UILabel for showing the score, a Buy a Life UIButton for adding lives, and a Restart UIButton for returning to the GameViewController.

代码如下:

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
        }
    }
}


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


This is how you wire up the forward segue to be called programmatically:

Control -从 ViewController 图标拖动到 MenuViewController :

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

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

Click on the segue arrow between the viewControllers and give it an identifier in the Attributes Inspector:

这是连接 unwind segue 以编程方式调用的方式:

This is how you wire up the unwind segue to be called programmatically:

Control -从 ViewController 图标拖动到 Exit 图标:

Control-drag from ViewController icon to Exit icon:

从弹出窗口中选择 returnFromMenu :

点击文档大纲中的 Unwind Segue ,然后在 Attributes Inspector中为其赋予标识符"Back" 右边的em>:

Click on the Unwind Segue in the Document Outline and give it the identifier "Back" in the Attributes Inspector on the right:

替代答案

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

Instead of using segues, you can present and dismiss viewControllers manually. The advantage for your app is that the MenuViewController will be allocated only once and will persist for the life of the app. This same viewController will be presented and dismissed repeatedly, but it will not be deallocated which I suspect is leading to your crashes.

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

The GameViewController will be the initialViewController that is created by the Storyboard. The MenuViewController will be loaded in viewDidLoad of the GameViewController.

要执行此操作,您需要向MenuViewController添加一个标识符,以便可以通过名称实例化它.单击情节提要中的MenuViewController,然后在 Identity Inspector 中设置其 Storyboard ID :

To make this work, you need to add an identifier to the MenuViewController so that it can be instantiated by name. Click on the MenuViewController in the Storyboard and set its Storyboard ID in the Identity Inspector:

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

Here is the code. Note that all mention of segues is gone. Note how viewWillAppear is used to update the 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)
    }
}

这篇关于在模态Segues之后需要释放内存,但是我需要我的两个Segues才能将数据从A传递到B并将B传递到A的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆