我如何在不使用 segue 的情况下将大量数据从 viewController 传递到另一个?

how can i pass alot of data from viewController to another on without using segue?

我想在不使用 segue 的情况下将 UIimage 从 viewController 传递到另一个,我一直在寻找这个问题数周。另外,我尝试使用 notificationCenter、delegate 和 protocol 来做到这一点,但它对我不起作用,所以请帮忙。

这是一个屏幕截图,描述了我想要做的事情。

enter image description here

此外,这是我的 viewController 代码,我想在单击传递标签按钮时从中传递雷神图像。

            import UIKit

  protocol UserChosePhoto {
  func userHasChosen(image: UIImage)
  }


class passingDataViewController: UIViewController {

@IBOutlet var Label: UILabel!
@IBOutlet var image1: UIImageView!

var image: UIImage? = nil
  var delegate: UserChosePhoto? = nil




override func viewDidLoad() {
    super.viewDidLoad()
    
    
  image1.image = image
   
    
    
   
}

@IBAction func passLabel(_ sender: Any) {
    
    
   func tapped() {
       if (delegate != nil) {
           self.delegate!.userHasChosen(image: image1.image!)
       }
 
 
}

}
}

这是 viewController 的代码,我想在其中显示雷神图像。

   import UIKit


   class receivingDataViewController: UIViewController, UserChosePhoto {



   @IBOutlet var label2: UILabel!
  
   @IBOutlet var image2: UIImageView!

   var usedImage: UIImage? = nil




   override func viewDidLoad() {
    super.viewDidLoad()

    
  
    
   }



   func userHasChosen(image: UIImage) {
       usedImage = image
    print("delegation: \(image)")
    
   }
    
    
    


}



          

尝试使用 public 变量。它可以让你在其中存储任何你想要的东西,并从你项目的任何地方访问它。 例如,将此行放在任何 class:

之外的任何地方
public var userImage: UIImage? = nil

然后您可以在您的代码中任何地方使用它,方法是像使用任何其他变量一样使用userImage

或者,如果你有多个变量,你可以创建一个带有静态变量的结构:

struct sharedVariables {
    static var userImage: UIImage? = nil
    static var userList: [Any] = [64, "Hello, world!"]
    static var integer: Int = 300
    // Or add anything you want; just make sure to start with 'static'
}

然后你可以像这样使用结构中的变量:

sharedVariables.userList

当然,还有很多方法可以实现您的要求,但这是最简单的一种。

我发现缺少一些东西,还有一些 Swift 编码约定没有得到遵守。那么让我们从您的 UserChosePhoto 协议开始吧,它非常好。但是 - 为什么不让您的代码可读?

protocol PassingDataViewControllerDelegate {
      func userHasChosen(image: UIImage)
}

当然,你所拥有的会起作用,但是在你名字的末尾添加 Delegate(连同 VC 你正在使用它)让每个人都知道你在做什么。

现在您需要正确设置您的第一个视图控制器:

class PassingDataViewController: UIViewController {

    var delegate: PassingDataViewControllerDelegate? = nil
    func tapped() {
        if (delegate != nil) {
           self.delegate!.userHasChosen(image: image1.image!)
        }
    }
}

同样,非常 接近您的代码 - 我只是将您的视图控制器的 class 名称大写。 Swift 程序员就是这样做的。哦,因为我更改了门户的名称,所以需要更改为。

但是还有一件事 - 你有 second 的编码方式:

class PassingDataViewController: UIViewController {

    var delegate: PassingDataViewControllerDelegate! = nil
    func tapped() {
        delegate.userHasChosen(image: image1.image)
    }
}

这会导致一些结果。显然,委托调用更简单。但更重要的是,如果您没有在第二个视图控制器中正确设置内容,您的应用程序就会崩溃。 (有时候,这实际上是一件好事!)

这是我认为你做错的地方 - 第二个 VC:

class ReceivingDataViewController: UIViewController, PassingDataViewControllerDelegate {

    var usedImage: UIImage? = nil
    let passingDataViewController = PassingDataViewController()

    override func viewDidLoad() {
        super.viewDidLoad()
        passingDataViewController.delegate = self    
    }
    func userHasChosen(image: UIImage) {
        usedImage = image
        print("delegation: \(image)")
    }
}

现在,有几件事。

首先,请注意,我正在创建第一个 VC 的 实例 - 这是必需的。授权始终是一种 1:1 的沟通方式。 仍然 缺少的(因为你没有在你的问题中提到它)是 如何 第一个 VC 被呈现。我知道您不想使用 segue,但是您的应用程序如何从第一个视图控制器“流”到第二个视图控制器?通常没有 segue 这意味着以模态方式呈现它(就像你使用 UIImagePickerController 一样)。您还可以添加视图控制器和它的视图作为子视图 VC 并在层次结构中查看。

其次,我告诉第一个 VC 第二个 VC 是它的代表。如果你不使用可选项 (var delegate: PassingDataViewControllerDelegate? = nil) 而使用 force-unwrap 东西 (var delegate: PassingDataViewControllerDelegate! = nil) 你会看到你的应用程序崩溃,因为第二个 VC 不是第一个 VC 没有 passingDataViewController.delegate = self.

最后说明:

在我写这篇文章时@TLG_Codin 提供了一个答案。它 可以 工作 - 但是 *userImage 在哪里声明为 public 变量?在两个地方之一:

  • 在全球范围内,如在 class 之外。这称为 单例,并且在执行此操作时要非常非常小心。由于它是全球性的,因此您应用中的 anyplace 可以更改它。这就是为什么单身人士通常不受欢迎的原因。
  • 在你的第一个 VC 里面。问题是 - 你如何呈现这个 VC?同样,您已经提到您不想使用 segue。所以...你回到我关于从第二个 VC 呈现第一个 VC 或添加 VC 及其视图到层次结构的注释。无论哪种方式?委派工作完美,在时刻你想告诉感兴趣的classes(在本例中是第二个VC)userImage已经改变了,你知道。