Search code examples
iosswiftxcodeappdelegateuiswitch

How do I send the switch data as an array in the app delegate


I have an ios app with multiple switches in a view controller. I need to send that data from those switches to the next view controller, which will send it to the database. I am using the app delegate as the middle man.

To solve this, Below is the code i am using in the view controller.

//  ViewController.swift
//  DepressionApp1
//
//  Created by Ashok Nambisan on 10/30/22.
//

import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    @IBOutlet weak var imageview: UIImageView!
    var switche: Int = 0
    var switche1: Int = 0
   
    @IBOutlet weak var switchButton1: UISwitch!
    @IBOutlet weak var switchButton: UISwitch!
    override func viewDidLoad() {
        super.viewDidLoad()
        if let imageData = UserDefaults.standard.data(forKey: "imageData") {
            let image = UIImage(data: imageData)
            imageview.image = image
        
               }
        switchButton.isOn = false
                    let switchValue = UserDefaults.standard.integer(forKey: "switchValue")
                    switchButton.isOn = (switchValue == 1)
        switchButton1.isOn = false
                    let switchValue1 = UserDefaults.standard.integer(forKey: "switchValue")
                    switchButton1.isOn = (switchValue1 == 1)
    }
    @IBAction func switchChanged1(_ sender: UISwitch) {
        switche1 = sender.isOn ? 1 : 0
                  UserDefaults.standard.set(switche1, forKey: "switchValue1")
               let appDelegate = UIApplication.shared.delegate as! AppDelegate
               appDelegate.switche1 = switche1
    }
    @IBAction func switchChanged(_ sender: UISwitch) {
        switche = sender.isOn ? 1 : 0
                  UserDefaults.standard.set(switche, forKey: "switchValue")
               let appDelegate = UIApplication.shared.delegate as! AppDelegate
               appDelegate.switche = switche
       }
    @IBAction func Btnimagepicker(_ sender: Any) {
        let picker = UIImagePickerController()
        picker.allowsEditing=true
        picker.delegate=self
        present(picker, animated:true)
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let image=info[.editedImage] as? UIImage else {return}
        imageview.image=image
        
        let imageData = image.jpegData(compressionQuality: 0.5)
        UserDefaults.standard.set(imageData, forKey: "imageData")
            if let imageData = imageData {
                
                let imageDataBase64String = imageData.base64EncodedString()
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                appDelegate.myData = imageDataBase64String
                

            }
       
        dismiss(animated:true)
    
    }
    
    @IBAction func didTapButton(){
        let vc = storyboard?.instantiateViewController(withIdentifier: "second") as! SecondViewController
        vc.modalPresentationStyle = .fullScreen
        present(vc,animated: true)
    }
}

I basically initialize the switch, then use a function to send that data to the database. Then I add this into the app delegate.

var switche: Any?

And use this code to call it in the third view controller.


`let switche = appDelegate.switche

However, while this code works for 1 or 2 switches, i need 6 switches in this view controller, and 27 in the next. The problem is i have to repeat the switchChanged function for every new switch. I was wondering if I could find a better and more efficient method, maybe storing the switches in an array in the app delegate, instead of individual variables. Or perhaps there is an easier way to do all of this? This is my first IOS app so could someone help me


Solution

  • 1. How to collect switch data using an array

    To be fair, I'll suggest to use a dictionary instead of an array. Here's what I would do:

    • Write only one method @IBAction func switchChanged(_ sender: UISwitch)
    • In your storyboard, bind ALL of the switches action to your switchChangedmethd
    • Also in your storyboard, make every switch unique. There are a number of UISwitch properties that you can use to accomplish that, amongst others:
      • restorationIdentifier
      • accessibilityIdentifier
      • tag enter image description here

    I'll use the accessibilityIdentifier in this example, but choose what suits your use case best.

    Next, you declare a dictionary in your ViewController to hold all the switches' states, and update that in your switchChanged method. The sender parameter will tell us which switch the user changed.

    class ViewController: UIViewController {
        private var switchStates: [String: Bool] = [:]
    
        @IBAction func switchChanged(_ sender: UISwitch) {
            guard let identifier = sender.accessibilityIdentifier else {
                return
            }
            switchStates[identifier] = sender.isOn
        }
    }
    

    2. Passing data to your next ViewController without the AppDelegate

    Well, just pass your collection of SwitchStates along in didTapButton. Of course, your SecondViewController needs a switchStates property for this.

    @IBAction func didTapButton(){
        let vc = storyboard?.instantiateViewController(withIdentifier: "second") as! SecondViewController
        vc.modalPresentationStyle = .fullScreen
        vc.switchStates = switchStates
        present(vc,animated: true)
    }
    

    3. Bonus tip

    Use a Storyboard Segue instead of manually instantiating your next ViewController and navigating to it! In this case you would bind your button I directly to the segue in your storyboard, and you would pass your switchStates in func prepare(for segue: UIStoryboardSegue, sender: Any?)