gpt4 book ai didi

swift - 需要在 Modal Segues 之后释放内存,但我需要两个 Segues 将数据从 A 传递到 B 以及从 B 传递到 A

转载 作者:行者123 更新时间:2023-11-30 10:09:34 26 4
gpt4 key购买 nike

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

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

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

我需要关闭每次调用 segue 时创建的附加 View 。

问题是:我需要“丢失”Segue 将有关分数的数据发送到 View B,并且需要“返回”Segue 将有关玩家是否使用生命的数据发送到 View A。

我已经实现了这一切。但现在我需要找到如何消除旧 View ,这些 View 不断消耗设备内存,从而导致滞后和崩溃。

我在谷歌上搜索了好几个小时。没有适合我的情况的解决方案。

我发现的解决方案要么导致我的应用程序出现错误,要么导致数据无法传递,要么无法生成 View 。

我不会在这里添加代码,因为有很多代码。但我确信答案实际上非常简单,只是不适合像我这样的初学者。

我认为一个可能的解决方案是从 B 到 A 的展开转场?

但是展开转场会传递数据吗?

此外,我没有找到我能理解的关于如何使用展开转场的答案。

我用尽了所有的可能性。 Stack Exchange 是我最后的机会。

最佳答案

你绝对应该使用unwind segue来返回到之前的viewController,否则你会发现你的内存使用量会增加,直到你的应用程序退出。

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

GameViewController 有一个玩家死亡 UIButton、一个用于输入分数的 UITextField 和一个 UILabel 用于显示生命。

MenuViewController 有一个用于显示分数的 UILabel,一个用于添加生命的 Buy a Life UIButton,和一个重新启动 UIButton 用于返回GameViewController

storyboard overview

代码如下:

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:

control drag to set up segue

<小时/>

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

picture of pop-up

<小时/>

单击 View Controller 之间的segue 箭头,并在属性检查器中为其指定一个标识符:

identifier in attributes inspector

<小时/>

这是连接要以编程方式调用的展开转场的方式:

Control - 从 ViewController 图标拖动到 退出 图标:

set up unwind segue

<小时/>

从弹出窗口中选择returnFromMenu:

choose return from Menu

<小时/>

单击文档大纲中的Unwind Segue,并在属性检查器中为其指定标识符“后退” em> 右边:

enter image description here

<小时/>

替代答案

您可以手动呈现和关闭 View Controller ,而不是使用segues。您的应用程序的优点是 MenuViewController 将仅分配一次,并将在应用程序的生命周期中持续存在。这个相同的 viewController 将被重复地呈现和关闭,但它不会被释放,我怀疑这会导致你的崩溃。

GameViewController 将是 Storyboard 创建的初始ViewController。 MenuViewController 将在 GameViewControllerviewDidLoad 中加载。

要实现此功能,您需要向 MenuViewController 添加一个标识符,以便可以通过名称对其进行实例化。单击 Storyboard 中的 MenuViewController,然后在身份检查器中设置其 Storyboard ID:

set storyboard ID

<小时/>

这是代码。请注意,所有提及的 segues 都消失了。请注意如何使用 viewWillAppear 来更新 viewController。

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

关于swift - 需要在 Modal Segues 之后释放内存,但我需要两个 Segues 将数据从 A 传递到 B 以及从 B 传递到 A,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33715078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com