我如何在不使用 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
已经改变了,你知道。
我想在不使用 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
已经改变了,你知道。