如何在 ViewController 之间传输数据?
How to transfer data between ViewControllers?
我目前正在开发货币汇率应用程序。我有一个 main
ViewController,它有一个 UILabel,它显示 selected 货币的解析汇率。此外,还有一个按钮用于更改其中一种货币汇率以获得新汇率(second
ViewController 显示为 N tableView 单元格).
我在将新 selected 值的数据传输到 main
ViewController 时遇到了一些麻烦。当我 select 一个新的汇率时,我得到了 UILabel 的这个错误:
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
我想我知道如何修复它 - 在 main
中创建一个变量并在 second
viewcontroller 中设置它的值,但我不知道如何正确地做。这是我的代码。提前致谢。
class MainVC: UITableViewController {
var convertedValue: String = ""
// some stuff
func parseCurrency(top: String) {
let URL_Exchange = URL(string: "MY URL\(top)")!
let task = URLSession.shared.dataTask(with: URL_Exchange) {(data, response, error) in
guard let data = data else { return }
let queue = DispatchQueue(label: "result")
queue.async {
let JSON = String(data: data, encoding: .utf8)
let jsonData = JSON!.data(using: .utf8)!
let result: Rates = try! JSONDecoder().decode(Rates.self, from: jsonData)
let currencies = result.conversion_rates?.dictionary
var doubleVar:Double = 0
for item in currencies! {
if (item.key == self.BottomCurrency.sublabel) {
doubleVar = item.value as! Double
}
}
// this value is the text to print inside "Result" Label
let mult = Double(round(10000*doubleVar * self.InputText)/10000)
self.convertedValue = String(mult)
DispatchQueue.main.async {
if self.convertedValue == "0" {
self.Result.text = String(0)
} else {
// Here I get an error
self.Result.text = self.formatNumber(num: Double(self.convertedValue))
}
}
}
}
task.resume()
}
second
的代码VC:
class SecondVC: UITableViewController {
private var temp: Int = 0
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if isBeingDismissed {
// updating temp value...
let vc = storyboard!.instantiateViewController(withIdentifier: "main") as! MainVC
vc.parseCurrency(top: Currencies[temp].short)
// or to call vc.convertedValue = something
// vc.parseCurrency(...)
}
}
如果我不得不猜测,您的代码崩溃的原因是您在新创建的 main
视图控制器实例上调用的 属性 Result
实际上是IBOutlet
指向尚未创建的 UILabel!
。
重要!
Internet 上有大量关于在视图控制器之间传递数据的资源,因此我将您指向已经存在的 post,并提供了大量答案:Passing data between view controllers
但是,我将在下面描述一种可用的解决方法
委派
解决它的一种方法是使用“传统的”UIKit 模式,即 Delegation
。
您只需创建一个协议,即可实现 secondVC
与 mainVC
通信的方式
protocol SecondVCDelegate: AnyObject {
func secondVCDidSelect(currency: String)
}
然后你在secondVC
上加一个weak
属性
class SecondVC: UITableViewController {
weak var delegate: SecondVCDelegate?
// ...
}
现在您应该可以将您想要的任何值传递给委托。为了这个例子,你可以在 temp
属性
的 didSet
观察者上做
class SecondVC: UITableViewController {
private var temp: Int = 0 {
didSet {
delegate?.secondVCDidSelect(currency: Currencies[temp].short)
}
}
weak var delegate: SecondVCDelegate?
}
Personally I would call the delegate the moment user is selecting the value, and not store it in the temp
property
唯一缺少的是将 mainVC
设置为 secondVC
的委托并遵守协议。完美的地方是在你展示来自 mainVC
的 secondVC
的那一刻
let viewController: SecondVC = // init SecondVC or load from storyboard
viewController.delegate = self
// present secondVC
extension MainVC: SecondVCDelegate {
func secondVCDidSelect(currency: String) {
parseCurrency(top: currency)
}
}
我鼓励您阅读更多关于委托的内容,因为这是 iOS 开发中非常流行的模式
Delegation in Swift 约翰·桑德尔
我目前正在开发货币汇率应用程序。我有一个 main
ViewController,它有一个 UILabel,它显示 selected 货币的解析汇率。此外,还有一个按钮用于更改其中一种货币汇率以获得新汇率(second
ViewController 显示为 N tableView 单元格).
我在将新 selected 值的数据传输到 main
ViewController 时遇到了一些麻烦。当我 select 一个新的汇率时,我得到了 UILabel 的这个错误:
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
我想我知道如何修复它 - 在 main
中创建一个变量并在 second
viewcontroller 中设置它的值,但我不知道如何正确地做。这是我的代码。提前致谢。
class MainVC: UITableViewController {
var convertedValue: String = ""
// some stuff
func parseCurrency(top: String) {
let URL_Exchange = URL(string: "MY URL\(top)")!
let task = URLSession.shared.dataTask(with: URL_Exchange) {(data, response, error) in
guard let data = data else { return }
let queue = DispatchQueue(label: "result")
queue.async {
let JSON = String(data: data, encoding: .utf8)
let jsonData = JSON!.data(using: .utf8)!
let result: Rates = try! JSONDecoder().decode(Rates.self, from: jsonData)
let currencies = result.conversion_rates?.dictionary
var doubleVar:Double = 0
for item in currencies! {
if (item.key == self.BottomCurrency.sublabel) {
doubleVar = item.value as! Double
}
}
// this value is the text to print inside "Result" Label
let mult = Double(round(10000*doubleVar * self.InputText)/10000)
self.convertedValue = String(mult)
DispatchQueue.main.async {
if self.convertedValue == "0" {
self.Result.text = String(0)
} else {
// Here I get an error
self.Result.text = self.formatNumber(num: Double(self.convertedValue))
}
}
}
}
task.resume()
}
second
的代码VC:
class SecondVC: UITableViewController {
private var temp: Int = 0
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if isBeingDismissed {
// updating temp value...
let vc = storyboard!.instantiateViewController(withIdentifier: "main") as! MainVC
vc.parseCurrency(top: Currencies[temp].short)
// or to call vc.convertedValue = something
// vc.parseCurrency(...)
}
}
如果我不得不猜测,您的代码崩溃的原因是您在新创建的 main
视图控制器实例上调用的 属性 Result
实际上是IBOutlet
指向尚未创建的 UILabel!
。
重要!
Internet 上有大量关于在视图控制器之间传递数据的资源,因此我将您指向已经存在的 post,并提供了大量答案:Passing data between view controllers
但是,我将在下面描述一种可用的解决方法
委派
解决它的一种方法是使用“传统的”UIKit 模式,即 Delegation
。
您只需创建一个协议,即可实现 secondVC
与 mainVC
protocol SecondVCDelegate: AnyObject {
func secondVCDidSelect(currency: String)
}
然后你在secondVC
weak
属性
class SecondVC: UITableViewController {
weak var delegate: SecondVCDelegate?
// ...
}
现在您应该可以将您想要的任何值传递给委托。为了这个例子,你可以在 temp
属性
didSet
观察者上做
class SecondVC: UITableViewController {
private var temp: Int = 0 {
didSet {
delegate?.secondVCDidSelect(currency: Currencies[temp].short)
}
}
weak var delegate: SecondVCDelegate?
}
Personally I would call the delegate the moment user is selecting the value, and not store it in the
temp
property
唯一缺少的是将 mainVC
设置为 secondVC
的委托并遵守协议。完美的地方是在你展示来自 mainVC
secondVC
的那一刻
let viewController: SecondVC = // init SecondVC or load from storyboard
viewController.delegate = self
// present secondVC
extension MainVC: SecondVCDelegate {
func secondVCDidSelect(currency: String) {
parseCurrency(top: currency)
}
}
我鼓励您阅读更多关于委托的内容,因为这是 iOS 开发中非常流行的模式
Delegation in Swift 约翰·桑德尔