Reload View wenn Button gedrückt wird

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Reload View wenn Button gedrückt wird

    Hallo zusammen,

    ich bin auf mein nächstes Problem gestoßen und komme nicht so recht weiter weil mir der Einstieg fehlt, oder besser gesagt das Hintergrundwissen ;(

    Problem/Frage
    Ich habe eine App die sich Daten aus dem Internet holt (JSON), diese parsed und dann ein bisschen rechnet und das Ergebnis in Labels anzeigt.
    Das habe ich mit Eurer Hilfe auch schon so weit hinbekommen. Nun benötige ich einen "Reload/Refresh" Button der beim betätigen die Daten erneut holt, die Berechnungen, etc, anstellt und dann die Labels aktualisiert.

    Beim "stöbern" im Internet habe ich dazu zwar einiges gefunden, bin daraus aber nicht so recht schlau geworden. Was ich meine verstanden zu haben ist die Tatsache das es ein No-Go ist viewDidLoad manuell einfach aufzurufen !? Vielleicht habe ich das aber auch im Zusammenhang falsch interpretiert.

    Hier mal mein Code, der anscheinend funktioniert (self.viewDidLoad), sprich beim drücken des Button wird das Date Label aktualisiert. Ich bin aber sehr verunsichert ob das nur rein zufällig funktioniert und generell eine schlechte Lösung ist.

    Wäre über Eure Einschätzung und Tipps wie immer sehr dankbar :)


    Quellcode

    1. import UIKit
    2. import Foundation
    3. struct Currency: Decodable {
    4. var EUR_USD: Double
    5. var USD_EUR: Double
    6. }
    7. class ViewController: UIViewController {
    8. @IBOutlet weak var labelDate: UILabel!
    9. @IBOutlet weak var labelCurrency: UILabel!
    10. @IBAction func reloadView(_ sender: Any) {
    11. print("Reload View")
    12. self.viewDidLoad()
    13. }
    14. override func viewDidLoad() {
    15. super.viewDidLoad()
    16. // Do any additional setup after loading the view.
    17. let urlString = "https://free.currconv.com/api/v7/convert?q=USD_EUR,EUR_USD&compact=ultra&apiKey=123456789"
    18. let url = URL(string: urlString)
    19. let session = URLSession.shared
    20. let dataTask = session.dataTask(with: url!) { [self] (data, reponse, error) in
    21. // check for errors
    22. if error == nil && data != nil {
    23. // parse json
    24. do {
    25. // Aktuelles Abfrage Datum ermitteln und formatieren
    26. // Referenz: https://www.ralfebert.de/ios/swift-dateformatter-datumsangaben-formatieren/
    27. let formatter = DateFormatter()
    28. formatter.locale = .init(identifier: "de")
    29. formatter.dateStyle = .medium
    30. formatter.timeStyle = .medium
    31. let dateFormattedString = formatter.string(from: Date())
    32. let currency: Currency = try! JSONDecoder().decode(Currency.self, from: data!)
    33. // Werte der Label im MainTask setzen
    34. DispatchQueue.main.async {
    35. labelDate.text = dateFormattedString
    36. labelCurrency.text = String(currency.EUR_USD)
    37. }
    38. }
    39. }
    40. }
    41. // Make the API call
    42. dataTask.resume()
    43. }
    44. }
    Alles anzeigen
    Gruß

    Ralf
  • ralfb schrieb:


    Was ich meine verstanden zu haben ist die Tatsache das es ein No-Go ist viewDidLoad manuell einfach aufzurufen !?
    Einfach einmal als Gedanken in den Raum geworfen: Was spricht dagegen, eine Methode loadData o.ä. zu haben, die sowohl aus viewDidLoad heraus als auch über einen Button aufgerufen wird...?

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • :?: :?: :?:
    Ich habe folgendes probiert, führt aber dazu das gar keine Daten mehr angezeigt werden, da vermutlich der "Thread Ablauf", sprich wann was geholt wird, nicht mehr passt.

    Quellcode

    1. import UIKit
    2. import Foundation
    3. // Variables
    4. var dateFormattedString = ""
    5. var currencyEUR_USD = 0.0
    6. struct Currency: Decodable {
    7. var EUR_USD: Double
    8. var USD_EUR: Double
    9. }
    10. func loadData() {
    11. let urlString = "https://free.currconv.com/api/v7/convert?q=USD_EUR,EUR_USD&compact=ultra&apiKey=4952f1f9652ee73bff5e"
    12. let url = URL(string: urlString)
    13. let session = URLSession.shared
    14. let dataTask = session.dataTask(with: url!) { (data, reponse, error) in
    15. // check for errors
    16. if error == nil && data != nil {
    17. // parse json
    18. do {
    19. // Aktuelles Abfrage Datum ermitteln und formatieren
    20. // Referenz: https://www.ralfebert.de/ios/swift-dateformatter-datumsangaben-formatieren/
    21. let formatter = DateFormatter()
    22. formatter.locale = .init(identifier: "de")
    23. formatter.dateStyle = .medium
    24. formatter.timeStyle = .medium
    25. dateFormattedString = formatter.string(from: Date())
    26. let currency: Currency = try! JSONDecoder().decode(Currency.self, from: data!)
    27. currencyEUR_USD = currency.EUR_USD
    28. }
    29. }
    30. }
    31. // Make the API call
    32. dataTask.resume()
    33. }
    34. class ViewController: UIViewController {
    35. @IBOutlet weak var labelDate: UILabel!
    36. @IBOutlet weak var labelCurrency: UILabel!
    37. @IBAction func reloadView(_ sender: Any) {
    38. print("Reload View")
    39. //self.viewDidLoad()
    40. loadData()
    41. }
    42. override func viewDidLoad() {
    43. super.viewDidLoad()
    44. // Do any additional setup after loading the view.
    45. loadData()
    46. // Werte der Label im MainTask setzen
    47. DispatchQueue.main.async { [self] in
    48. self.labelDate.text = dateFormattedString
    49. labelCurrency.text = String(currencyEUR_USD)
    50. }
    51. }
    52. }
    Alles anzeigen
    Wenn ich zur Kontrolle ein print() in den do{} Zweig der loadData Methode einbaue werden die aktuellen Werte auf der Konsole ausgegeben wenn die App startet und wenn ich den Reload Button drücke.

    Mir fehlt also noch das Stückchen wie ich das aktualisieren der Labels in viewDidLoad regeln kann ???

    Gruß

    Ralf
  • Ich habe mal ein sleep(10) hinter loadData() im viewDidLoad() eingebaut und dann werden die Daten in den Labels beim starten der App angezeigt.
    Das bestätigt mich in der Vermutung das der ViewController schon "durch ist" wenn loadData die Daten am Start hat und die Variablen gesetzt werden.

    Mir fehlt sozusagen ein Listener der die Daten in den Labels updated sobald die Variablen verändert wurden .. oder so etwas in der Art ;)

    Gruß

    Ralf
  • :whistling: zu einfach ... sorry ... wie blöd von mir .. X/
    Ich bin schon ein ziemlicher Depp ... was meinst Du - muss ich mich ernsthaft fragen ob ich zu blöd bin um das alles zu lernen?

    Hier mal als Referenz, falls es mal jemand benötigt - mein ganzer Code, der jetzt dank @MyMattes einwandfrei funktioniert :!: :!:

    Quellcode

    1. import UIKit
    2. import Foundation
    3. // Variables
    4. var dateFormattedString = ""
    5. var currencyEUR_USD = 0.0
    6. struct Currency: Decodable {
    7. var EUR_USD: Double
    8. var USD_EUR: Double
    9. }
    10. class ViewController: UIViewController {
    11. @IBOutlet weak var labelDate: UILabel!
    12. @IBOutlet weak var labelCurrency: UILabel!
    13. @IBOutlet weak var progressIndicator: UIActivityIndicatorView!
    14. @IBAction func reloadView(_ sender: Any) {
    15. print("Reload View")
    16. //self.viewDidLoad()
    17. loadData()
    18. }
    19. func loadData() {
    20. let urlString = "https://free.currconv.com/api/v7/convert?q=USD_EUR,EUR_USD&compact=ultra&apiKey=123456789"
    21. let url = URL(string: urlString)
    22. let session = URLSession.shared
    23. let dataTask = session.dataTask(with: url!) { (data, reponse, error) in
    24. // check for errors
    25. if error == nil && data != nil {
    26. // parse json
    27. do {
    28. // Aktuelles Abfrage Datum ermitteln und formatieren
    29. // Referenz: https://www.ralfebert.de/ios/swift-dateformatter-datumsangaben-formatieren/
    30. let formatter = DateFormatter()
    31. formatter.locale = .init(identifier: "de")
    32. formatter.dateStyle = .medium
    33. formatter.timeStyle = .medium
    34. dateFormattedString = formatter.string(from: Date())
    35. let currency: Currency = try! JSONDecoder().decode(Currency.self, from: data!)
    36. currencyEUR_USD = currency.EUR_USD
    37. // Werte der Label im MainTask setzen
    38. DispatchQueue.main.async {
    39. self.labelDate.text = dateFormattedString
    40. self.labelCurrency.text = String(currencyEUR_USD)
    41. }
    42. }
    43. }
    44. }
    45. // Make the API call
    46. dataTask.resume()
    47. }
    48. override func viewDidLoad() {
    49. super.viewDidLoad()
    50. // Do any additional setup after loading the view.
    51. loadData()
    52. }
    53. }
    Alles anzeigen
    Danke nochmal und noch einen schönen Rest Sonntag -- ich gehe jetzt erst einmal eine Runde mit dem Hund und denke über das erlernte nach ...

    Gruß

    Ralf
  • ralfb schrieb:

    Ich bin schon ein ziemlicher Depp ... was meinst Du - muss ich mich ernsthaft fragen ob ich zu blöd bin um das alles zu lernen?
    Hey, munter bleiben ... ich finde, Du schlägst Dich ziemlich gut! Fehler gehören dazu, die Frage ist, wie man mit ihnen umgeht: Analysieren, Abstrahieren, Eigeninitiative...

    Ich kann nicht für andere sprechen, aber ich sehe bei Dir keinen Grund zur Sorge ;) Da habe ich schon ganz andere Böcke geschossen!

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • ralfb schrieb:

    Wäre es im Prinzip möglich den Reload nicht über den Button sondern durch UIRefreshControl zu implementieren?

    Wenn ich die Doku richtig versteh [...] benötige ich dafür eine Scroll View oder z.B. eine TableView.
    Verstehe ich auch so, es macht auch Sinn, weil dieses Control ja ein Blättern jenseits des Contents zum Triggern benötigt - aber ich hab‘ dieses Element noch nie benutzt. Andere vor, wir müssen hier ja kein Zweiergespräch führen :)

    Mattes

    P.S.: Der Übersicht wegen fände ich bei neuen Fragen neue Threads hilfreich...
    Diese Seite bleibt aus technischen Gründen unbedruckt.