2 Replies
      Latest reply on Jan 8, 2019 5:10 PM by tekgeek1
      tekgeek1 Level 1 Level 1 (0 points)

        Here is my situation. I have some common processing code (function) in VC1 - this is common code that other view controllers will call. Basically, a user enters a value into say VC3 - VC1 will process the value.  Since I have multiple VC's who do the same actions for a different activity (e.g, enter weight lifted for legs vs fly) I want to minimize th common code.  It all works great as long as the VC2 and VC3 are directly wired to the VC1.

         

        I currently use the suegue approach but am stuck on this one.

         

        I suspect it is how I have the VC's wired and is simple to correct

         

        Help please!  Can post eisting code if that would assist.

        • Re: Non- adjacent view controllers
          jonprescott Level 2 Level 2 (70 points)

          A couple of questions and comments:

           

          1 - What do you mean about VC2 and VC3 being directly wired to VC1?  Did VC2 and VC3 have a reference to VC1 in their state (which you could setup by using an IBOutlet and connecting them????)?  Did you have notifications setup between VC1 and VC2/VC3? When they were wired, how did you get to the common code?

           

          2 - Is VC1 maintaining state or have references to other objects that VC2 and VC3 can't access except for going through VC1?  Does the common code have state variables or properties that it manipulates that are part of VC1?

           

          3 - Have you considered isolating the common code into a function that can be called from all 3 view controllers, thus, not requiring that there be any connection between the 3?

           

          4 - Where is your model being kept?  From your description, it seems like this code is model related, and should be part of your model code, not the controller code.  But, if it is code that, for example, translates units, that needs to be used by all the controllers, it probably needs to be factored out into a separate function.

            • Re: Non- adjacent view controllers
              tekgeek1 Level 1 Level 1 (0 points)

              #3 is exactly what I want to do.  My only requirement is to pass back data (core storage) to display data - I want the write-to-core, read-from-core to be in a common accessible space.  I thought using delegate and segue was the way to do that.  I can post or send code if that is helpful.

               

              Here is my VC1 with some common functions

              import UIKit
              import CoreData
              var valuetest = ""
              
              class TimeSensitiveChestWorkout1: UIViewController, WeightProtocol {
                  var Pressed: String!
              
                  
                  @IBOutlet weak var logo: UIImageView!
                  @IBOutlet weak var Workout1: UIButton!
                  @IBOutlet weak var Workout2: UIButton!
                  @IBOutlet weak var Workout3: UIButton!
              
                  @IBAction func didPressButton(sender:  AnyObject) {
                      Pressed = "DumbbellPress"
                      print ("*******  Dumbbell button pressed: ", Pressed!)
                  }
                  
                  @IBAction func inclineDumbbellPress(_ sender: Any) {
                      Pressed = "inclineViewController"
                      print (Pressed)
                  }
                  
                  
                  override func viewDidLoad() {
                      super.viewDidLoad()
              
                      // Do any additional setup after loading the view.
                      logo.layer.cornerRadius = 25
                      logo.layer.masksToBounds = true
                      logo.layer.borderColor = UIColor.white.cgColor
                      logo.layer.borderWidth = 3
                      
                      Workout1.layer.cornerRadius = 20
                      Workout1.layer.masksToBounds = true
                      Workout1.layer.borderColor = UIColor.white.cgColor
                      Workout1.layer.borderWidth = 2
                      
                      Workout2.layer.cornerRadius = 20
                      Workout2.layer.masksToBounds = true
                      Workout2.layer.borderColor = UIColor.white.cgColor
                      Workout2.layer.borderWidth = 2
                      
                      Workout3.layer.cornerRadius = 20
                      Workout3.layer.masksToBounds = true
                      Workout3.layer.borderColor = UIColor.white.cgColor
                      Workout3.layer.borderWidth = 2
                  }
                  
                  
                  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                      if (Pressed == "DumbbellPress") {
                          let destination = segue.destination as! DumbbellChestPress
                          destination.delegate = self
                      }
                      else if (Pressed == "inclineViewController") {
                          let destination = segue.destination as! inclineViewController
                          destination.delegate = self
                      }
                      else {
                          print ("******** No button press")
                      }
                  }
                  
                  
                  func updateDataGlobal(EntityVar: String, ExeriseNameVar: String, value:String){
                      guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
                      let managedContext = appDelegate.persistentContainer.viewContext
                      
                      let fetchRequest:NSFetchRequest = NSFetchRequest.init(entityName: EntityVar)
                  fetchRequest.predicate = NSPredicate(format: "name = %@", ExeriseNameVar)
                      do
                      {
                          let test = try managedContext.fetch(fetchRequest)
                          let objectUpdate = test[0] as! NSManagedObject
                          objectUpdate.setValue(value, forKey: "weight")
                          do{
                              try managedContext.save()
                              print ("Record Updated: ",value, " for: ", ExeriseNameVar)
                          }
                          catch
                          {
                              print("Error: ",error)
                          }
                      }
                      catch
                      {
                          print(error)
                      }
                  }
                  
                  
                  func retrieveDataGlobal(EntityVar: String, ExeriseNameVar: String, value:String) {
                      guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
                      let managedContext = appDelegate.persistentContainer.viewContext
                      
                      let fetchRequest = NSFetchRequest(entityName: "Chest")
                      
                      fetchRequest.fetchLimit = 5
                      fetchRequest.predicate = NSPredicate(format: "name = %@", ExeriseNameVar)
                      
                      let count = try! managedContext.count(for: fetchRequest)
                      print ("retrieveDataGlobal record count: ", count)
               //       if (count == 0){
               //           createData()
               //       }
                      print (count)
              
                      do {
                          let result = try managedContext.fetch(fetchRequest)
                          
                          for data in result as! [NSManagedObject] {
                              print("********** Data Retrieved - weight:  ", data.value(forKey: "weight") as! String)
                              valuetest = data.value(forKey: "weight") as! String
                              print ("+++++++++++++  valuetest: ", valuetest)
                          }
                      } catch {
                          print("Failed")
                      }
                  }
                  
              
              }

               

               

              Here is my VC2 which is connected direct in the storyboard but if there is another VC in the IOutlet path it doesnt work

              import UIKit
              import CoreData
              
              protocol WeightProtocol {
                  func updateDataGlobal(EntityVar: String, ExeriseNameVar: String, value:String)
                  func retrieveDataGlobal(EntityVar: String, ExeriseNameVar: String, value:String)
              }
              
              extension UIViewController {
                  func HideKeyboard() {
                      let Tap:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(DismissKeyboard))
                      view.addGestureRecognizer(Tap)
                  }
                  @objc func DismissKeyboard() {
                      view.endEditing(true)
                  }
              }
              
              class DumbbellChestPress: UIViewController {
                  var delegate: WeightProtocol!
              
                  @IBOutlet weak var newMaxLiftText: UITextField!
                  @IBOutlet weak var newMaxLiftLabel: UILabel!
                  @IBOutlet weak var maxWeightLiftedLabel: UILabel!
                  
                  @IBAction func newWeightButon(_ sender: UIButton) {
                      maxWeightLiftedLabel.text = newMaxLiftText.text
                      delegate?.updateDataGlobal(EntityVar: "Chest", ExeriseNameVar: "Dumbell Chest Press", value: maxWeightLiftedLabel.text!)
                      self.dismiss(animated: true, completion: nil)
              //        updateData()
                  }
                  
                  @IBAction func delerteDataBtton(_ sender: UIButton) {
                      deleteData()
                  }
                  
                  @IBAction func loadDataButton(_ sender: UIButton) {
                      createData()
                  }
                  
                  @IBOutlet weak var Workout1: UIImageView!
                  @IBOutlet weak var Workout2: UIImageView!
                  
                  @IBOutlet weak var Workout4: UIImageView!
                  @IBOutlet weak var Workout3: UIImageView!
                  
                  override func viewDidLoad() {
                      super.viewDidLoad()
                      self.HideKeyboard()
                      
                      delegate?.retrieveDataGlobal(EntityVar: "Chest", ExeriseNameVar: "Dumbell Chest Press", value: maxWeightLiftedLabel.text!)
              
                     maxWeightLiftedLabel.text = valuetest
                      
                      Workout1.layer.cornerRadius = 20
                      Workout1.layer.masksToBounds = true
                      Workout1.layer.borderColor = UIColor.white.cgColor
                      Workout1.layer.borderWidth = 2
                      
                      Workout2.layer.cornerRadius = 20
                      Workout2.layer.masksToBounds = true
                      Workout2.layer.borderColor = UIColor.white.cgColor
                      Workout2.layer.borderWidth = 2
                      
                      Workout3.layer.cornerRadius = 20
                      Workout3.layer.masksToBounds = true
                      Workout3.layer.borderColor = UIColor.white.cgColor
                      Workout3.layer.borderWidth = 2
                      
                      Workout4.layer.cornerRadius = 20
                      Workout4.layer.masksToBounds = true
                      Workout4.layer.borderColor = UIColor.white.cgColor
                      Workout4.layer.borderWidth = 2
              
                      // Do any additional setup after loading the view.
                  }
                 
              }