Search code examples
jsonswiftloopsuikitdecode

How to correctly switch JSON colours using UIButton?


Problem: I have JSON file, which contains some color's names and values(for example: "aliceblue": [240, 248, 255, 1], "antiquewhite": [250, 235, 215, 1], "aqua": [0, 255, 255, 1], etc). I'm trying to decode this one and apply color's value to background color after pressing button in current order. If Xcode decode file in order, for example, 4, 9, 1... and colors must apple in oder 4, 9, 1..., I think. But when I'm pushing button, colors change absolutely randomly (some colors may change several times in a row). Part of code:

 @IBAction func changeColor(_ sender: UIButton) {
    
    let path = Bundle.main.path(forResource: "colors",
                                     ofType: "json")
    let url = URL(fileURLWithPath: path!)
    
    do {
        let data = try Data(contentsOf: url)
        let colors: [String:[Int]] = try JSONDecoder()
                                         .decode([String:[Int]].self,
                                                  from: data)
        
        for i in colors.enumerated() {
            
            print(i.element.key)
            let rgbaArray = colors[i.element.key]
            let r = CGFloat(rgbaArray![0]) / 255
            let g = CGFloat(rgbaArray![1]) / 255
            let b = CGFloat(rgbaArray![2]) / 255
            let a = CGFloat(rgbaArray![3])
            
            label.text = i.element.key
            
            self.view.backgroundColor = UIColor(red: r,
                                              green: g,
                                               blue: b,
                                              alpha: a)
        }
    } catch {
        print("Error")
    }    
}

Question: What do I have to change in my code to make it work correctly?


Solution

  • Use the following approach:

    (pay attention to % operator – it allows to loop a sequence of 5 colors here)

    import UIKit
    
    class ViewController: UIViewController {
        
        @IBOutlet var label: UILabel!
        var colors = [String: [Int]]()
        var counter: Int = 0
        var arrayOfNames: [ String ] = []
        var arrayOfRGBAs: [ [Int] ] = []
        
        @IBAction func changeColor(_ sender: UIButton) {
    
            let r = CGFloat(arrayOfRGBAs[counter % 5][0]) / 255
            let g = CGFloat(arrayOfRGBAs[counter % 5][1]) / 255
            let b = CGFloat(arrayOfRGBAs[counter % 5][2]) / 255
            let a = CGFloat(arrayOfRGBAs[counter % 5][3])
    
            self.view.backgroundColor = UIColor(red: r,
                                              green: g,
                                               blue: b,
                                              alpha: a)
            
            self.label.text = arrayOfNames[counter % 5]
            
            self.counter += 1
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            self.label.text = "Choose a color"
                
            self.view.backgroundColor = .systemGray5
            
            let path = Bundle.main.path(forResource: "colors",
                                             ofType: "json")
            
            let url = URL(fileURLWithPath: path!)
                
            do {
                let data = try Data(contentsOf: url)
                
                self.colors = try JSONDecoder().decode([String:[Int]].self,
                                                        from: data)
    
                self.arrayOfNames.append(contentsOf: colors.keys)
                self.arrayOfRGBAs.append(contentsOf: colors.values)
    
            } catch {
                print("Error of decoding")
            }
        }
    }
    

    And here's a content of JSON file:

    {
      "red": [128, 0, 0, 1],
      "green": [0, 128, 0, 1],
      "blue": [0, 0, 128, 1],
      "purple": [128, 0, 128, 1],
      "teal": [0, 128, 128, 1]
    }
    

    enter image description here