get variable outside of the loop

hi


i have a problem with my code...


//
//  ViewController.swift
//  Copyright © 2017 Producer. All rights reserved.
//

import UIKit
import Foundation


struct CurrencyStore {
    var name: String
    var currencies: [Currency]
  
    struct Currency: Codable{
        var symbol1: String
        var symbol2: String
        var minLotSize: Double
        var minLotSizeS2: Double
        var maxLotSize: Double?
        var maxPrice: String
        var minPrice: String
    }
}

let json = """
{"e":"currency_limits","ok":"ok","data":{"pairs":[{"symbol1":"BTC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"100","maxPrice":"35000"},{"symbol1":"ETH","symbol2":"USD","minLotSize":0.1,"minLotSizeS2":2.5,"maxLotSize":1000,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BCH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":30,"minPrice":"50","maxPrice":"5128"},{"symbol1":"BTG","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"2048"},{"symbol1":"DASH","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"XRP","symbol2":"USD","minLotSize":10,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"0.005","maxPrice":"50"},{"symbol1":"ZEC","symbol2":"USD","minLotSize":0.01,"minLotSizeS2":2.5,"maxLotSize":null,"minPrice":"2.5","maxPrice":"1024"},{"symbol1":"BTC","symbol2":"EUR","minLotSize":0.01,"minLotSizeS2":2.2,"maxLotSize":30,"minPrice":"100.00","maxPrice":"35000"}]}}
""".data(using: .utf8)!

struct CurrencyStoreService: Decodable {
  
    let e: String
    let ok: String
    let data: NestedData
  
    struct NestedData: Decodable {
        let pairs: [CurrencyStore.Currency]
    }
}

extension CurrencyStore {
    init(from CurrencyStoreService: CurrencyStoreService) {
        name = CurrencyStoreService.ok
        currencies = []
    }
}


class ViewController: UIViewController {
  
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
      
        do {
            let serverData = try JSONDecoder().decode(CurrencyStoreService.self, from: json)
            print(serverData.data.pairs)
          
        } catch let jsonErr {
            print(jsonErr)
          
        }
      
    }
  
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
  
  
}


The problem is row 55.

serverData only exists in the do loop, how can i define that as a gloabl variable? i mean how shoud i do it that the variable can be used in all classes.

My problem is that i musst use this object in other classes and functions... in some other languages its simple to define an global Variable but i dont found any related topic for swift.

Accepted Reply

You already know how to declare a global variable, since your "json" variable in line 25 is global. So:


var serverData: CurrencyStoreService // specify the type because Swift can't infer it here
// but the above won't compile!


The problem you have to deal with is this: Swift requires all variables to have an initial value, and you don't know the initial value until you've decoded the JSON. There are 3 possible solutions:


1. Initialize it to a place-holder value, something like this:


var serverData = CurrencyStoreService () // some kind of "default" value


2. Make it an optional value:


var serverData: CurrencyStoreService? = nil


3. Make it an implicitly-unwrapped option (IUO), where it starts as nil, but will cause an error if used before the nil has been replaced by another value:


var serverData: CurrencyStoreService! // default value is nil


Then, in viewDidLoad, set the correct value:


        do {
            serverData = try JSONDecoder().decode(CurrencyStoreService.self, from: json)


Which of the 3 options you choose depends a bit on what turns out to be convenient for the rest of your code.


Note, however, that global variables (or even public static class variables, which are approximately the same thing) can lead you into trouble later. That's because a global variable tends to be used by lots of different parts of your code, and so all those parts (in effect) become dependent on each other. Changing one part can break other part, and after your code gets more complex it's hard to know what's affected by changing one part.


A better solution in this case might be to make "serverData" an instance variable of your ViewController, since you can't get the serverData without using a ViewController instance. Outside code can refer to "serverData" through the view controller, which provides much better-controlled access.

Replies

You already know how to declare a global variable, since your "json" variable in line 25 is global. So:


var serverData: CurrencyStoreService // specify the type because Swift can't infer it here
// but the above won't compile!


The problem you have to deal with is this: Swift requires all variables to have an initial value, and you don't know the initial value until you've decoded the JSON. There are 3 possible solutions:


1. Initialize it to a place-holder value, something like this:


var serverData = CurrencyStoreService () // some kind of "default" value


2. Make it an optional value:


var serverData: CurrencyStoreService? = nil


3. Make it an implicitly-unwrapped option (IUO), where it starts as nil, but will cause an error if used before the nil has been replaced by another value:


var serverData: CurrencyStoreService! // default value is nil


Then, in viewDidLoad, set the correct value:


        do {
            serverData = try JSONDecoder().decode(CurrencyStoreService.self, from: json)


Which of the 3 options you choose depends a bit on what turns out to be convenient for the rest of your code.


Note, however, that global variables (or even public static class variables, which are approximately the same thing) can lead you into trouble later. That's because a global variable tends to be used by lots of different parts of your code, and so all those parts (in effect) become dependent on each other. Changing one part can break other part, and after your code gets more complex it's hard to know what's affected by changing one part.


A better solution in this case might be to make "serverData" an instance variable of your ViewController, since you can't get the serverData without using a ViewController instance. Outside code can refer to "serverData" through the view controller, which provides much better-controlled access.