【问题标题】:how can i pass alot of data from viewController to another on without using segue?如何在不使用 segue 的情况下将大量数据从 viewController 传递到另一个?
【发布时间】:2020-08-09 21:38:22
【问题描述】:

我想在不使用 segue 的情况下将 UIimage 从 viewController 传递到另一个,并且我一直在寻找这个问题好几个星期。另外,我尝试使用 notificationCenter、delegate 和协议来做这件事,但它对我不起作用,所以请帮忙。

这是一个截图,描述了我想要做什么。

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

}
}

这是视图控制器的代码,我想在其中显示雷神图像。

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


}



          

【问题讨论】:

  • 你是如何从passingDataViewControllerreceivingDataViewController 的?你需要设置委托
  • @jawadAli 我该怎么做?我是 swift 的新手,阿里先生,请帮助我,因为我一直在寻找这个,我想要的正是将标签和图像从许多 viewControllers 传递给 TableViewCell,因为我正在构建一个商店应用程序,我想将它传递给购物车tableViewCell 所以,请帮帮我。
  • @jawadAli 请帮助 Ali 先生,至少我只想通过标签。

标签: arrays swift delegates protocols nsnotificationcenter


【解决方案1】:

我发现一些东西丢失了,还有一些 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!)
        }
    }
}

再次,非常接近您的代码 - 我只是将您的视图控制器的类名大写。这就是 Swift 编码人员的做法。哦,由于我更改了门户的名称,因此需要更改为。

但还有一件事 - 你有 第二种 方法来编写代码:

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 的 instance - 这是必需的。委派始终是一种 1:1 的沟通方式。 仍然缺少的是(因为您在问题中没有提到它)是如何呈现第一个 VC。我知道您不想使用 segue,但是您的应用程序“流程”如何从第一个视图控制器转到第二个视图控制器?通常没有 segue,这意味着以模态方式呈现它(就像你使用 UIImagePickerController 一样)。您还可以将视图控制器及其视图添加为子 VC 和层次结构中的视图。

其次,我要告诉第一个 VC,第二个 VC 是它的委托。如果不使用可选项 (var delegate: PassingDataViewControllerDelegate? = nil) 而是强制解包 (var delegate: PassingDataViewControllerDelegate! = nil),您会看到您的应用程序崩溃,因为第二个 VC 不是没有 passingDataViewController.delegate = self 的第一个 VC 的委托。

最后说明:

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

  • 在全球范围内,如在课堂之外。这称为 singleton,在执行此操作时要非常非常小心。由于它是全球性的,您应用中的任何地方都可以更改它。这就是为什么单身人士通常不受欢迎的原因。
  • 在您的第一个 VC 中。问题是——你是如何介绍这个 VC 的?再次,您提到您不想使用 segue。所以...你回到我关于从第二个 VC 呈现第一个 VC 或添加 VC 及其对层次结构的视图的说明。无论哪种方式?委派工作完美,此刻你想告诉感兴趣的类(在本例中是第二个 VC)userImage 发生了变化,你这样做了。

【讨论】:

    【解决方案2】:

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

    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
    

    当然,还有更多方法可以满足您的要求,但这是最简单的一种。

    【讨论】:

    • 我试过了,但没用 :( 你有推特向你展示我所做的一切吗?
    • 对您的回答投反对票深表歉意。阅读我的答案 - 特别是最后一个注释 - 以了解为什么我认为这不是一个有用的答案。委托是正确的途径,而不是公共变量——无论它在哪里声明。
    • 我明白你想说什么。但是你的方式是不必要的复杂。另一种回答我的方法是创建一个带有静态变量的结构(这就是我在我的项目中所做的,到目前为止它工作得很好)。所以我还是不明白为什么用这种复杂的方式创建一个协议会更好。
    猜你喜欢
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2020-05-23
    • 2013-03-07
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多