Swift - 在 segue 之后保存 ViewController 设置

Posted

技术标签:

【中文标题】Swift - 在 segue 之后保存 ViewController 设置【英文标题】:Swift - save ViewController set up after segue 【发布时间】:2019-11-08 17:59:16 【问题描述】:

目前我必须ViewControllers。您可以使用show-seguesViewControllerAViewControllerB 之间切换。问题是每次我切换回来时,ViewControllers 状态都会被重置。如何保存 ViewController 的设置?

从 A 到 B

    @IBAction func editButtonTapped(_ sender: Any) 
    let imageCollectionView = self.storyboard?.instantiateViewController(withIdentifier: "ImageCollectionVC") as! ImageCollectionViewController

    self.navigationController?.pushViewController(imageCollectionView, animated: true)

从 B 到 A

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    tappedImage = images[indexPath.row]
    performSegue(withIdentifier: "backToPopUpView", sender: self)


【问题讨论】:

“问题是每次我切换回来时,ViewControllers 状态都会被重置。”那么你实际上并没有切换回来。你能展示一些代码让我们知道你目前在做什么吗? 我编辑了我的问题 查看您的代码,您并没有在视图控制器之间来回移动,而是在每次更改时创建视图控制器的新实例。所以你实际上是在做 A > B > A1 > B1 > A2 > B2 等等,这就是为什么没有保留状态。您需要弹出视图控制器 B 才能返回到 A。顺便说一下,您也没有在 A 到 B 中使用 segue。 Passing Data between View Controllers的可能重复 @flanker 那我该怎么做呢? 【参考方案1】:

要在视图控制器之间移动以两种方式传递数据,您需要做一些事情

一致的导航方法:seguespush/popping 通过导航控制器或模态 presenting/dismissing,但不是将它们混合用于一个 A - B - A 过渡

允许将数据从子代传回父代的协议/委托。

在下面的示例中,导航是通过导航控制器进行的,并且使用图像作为如何将数据传递回父级的示例。在其他情况下调整它应该是微不足道的。

子类需要与其父类达成一致的接口以允许它进行通信。这是通过协议完成的。在这个例子中,我们为孩子提供了一种将更新后的图像传回给父母的方法:

protocol ClassBDelegate 
    func childVCDidComplete(with image: UIImage?)

然后在子类中创建一个委托变量,该变量可以指向任何采用协议的类(在这种情况下将是它的父类),然后使用该委托和协议的函数将图像数据传回。一旦数据通过委托传回,视图控制器 B 调用导航控制器的 popViewCntroller 方法来关闭自身并将焦点返回给视图控制器 A

class B: UIViewController 
    var delegate: ClassBDelegate?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
        tappedImage = images[indexPath.row]
        delegate?.childVCDidComplete(with: tappedImage)
        navigationController?.popViewController(animated: true)
    

为了使这一切正常工作,需要将子视图控制器的委托设置为指向其父视图控制器 (A),但在此之前,该类需要符合协议:

extension A: ClassBDelegate 
    func childVCDidComplete( with image: UIImage?) 
        self.image = image
    

现在,当实例化子视图控制器时,父母将自己设置为委托,从而完成通信循环。

Class A: UIViewController 
    var image: UIImage?

    @IBAction func editButtonTapped(_ sender: Any) 
        let imageCollectionView = self.storyboard?.instantiateViewController(withIdentifier: "ImageCollectionVC") as! ImageCollectionViewController
        imageCollectionView.delegate = self
        self.navigationController?.pushViewController(imageCollectionView, animated: true)
    

【讨论】:

抱歉,我正在努力在我的代码中实现这一点。我到底要在哪里实现 extensionprotocol 我使用AB 作为A 和B 视图控制器的简写,所以用各自的类名替换它们。然后,您可以在其自己的文件中或在与视图控制器 B 相同的文件中,在 import 语句和您的类定义之间实现协议。您将视图控制器 A 的扩展放在它的类定义下方 - 在最后一个 之后。在这里解释有关协议/代表的所有内容的范围太广了,但是如果您在 YouTube 上查看 Sean Allen 有一个非常好的视频教程。 我实现了它,但现在如果我点击一个项目没有任何反应 popViewController 即使被调用也不做任何事情,我用print 对其进行了测试 我怀疑您没有完全正确地实现它,或者您没有显示其他代码与它冲突,因为我从工作模型中复制了代码。什么项目什么都不做? popviewcontroller 仅在您最初使用 push(使用导航控制器)呈现视图控制器时才有效,而不是在您以模态方式呈现或使用 segue 时。【参考方案2】:

您创建了新的 ViewControllerA,并且您有以下结果 A -> B -> A。 但这不是真的,你应该解雇 ViewControllerB...

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    tappedImage = images[indexPath.row]
    self.dismiss(animated: true, completion: nil)
    //performSegue(withIdentifier: "backToPopUpView", sender: self)


【讨论】:

但我正在传递一个UIImage 与那个segue。如果我只是 self.dismiss 那张图片不会通过 您必须通过两种方式传递信息。 1.使用协议 2. 在 ViewControllerB 中,您必须具有“parentVC:ViewControllerA”或“vcA:ViewControllerA”属性...而在 ViewControllerA 中,您必须编写这一行 imageCollectionView.vcA = self。在 ViewControllerB 中你可以通过 self.vcA.image = tappedImage 你能详细说明一下吗?:) 我不能在 ViewControllerA 中写 imageCollectionView.vcA = self

以上是关于Swift - 在 segue 之后保存 ViewController 设置的主要内容,如果未能解决你的问题,请参考以下文章

Swift UI集合视图 - 如何在Cell中显示“segued”用户输入?

在 SWIFT 中关闭 segue 之前保存变量

Swift,SpriteKit,GameViewController 和 MainViewController 在 GameOver 之后的 Segue

Swift - 在 segue 之后释放前一个视图控制器

Swift 4:在 viewDidLoad 之后调用 prepare(for segue:)

使用 segue 在 View Controller 之间传递变量