0

I'm applying for a junior developer position and I've got a very specific task, that already took me 3 days to complete. Sounds easy - pass data to rootViewController. That's what I've done:

1)

   private func userDefaultsToRootController() {
        let input = textField.text!
        defaults.set(input, forKey: "SavedLabel")
        navigationController?.popViewController(animated: true)
    } 
  1. private func segueToRootViewController() { let destinationVC = MainScreen1() let input = textField.text!

      if input == "" { self.navigationController?.popToRootViewController(animated: true) }
    
      destinationVC.input = input
      navigationController?.pushViewController(destinationVC, animated: true)
    

    }

private func popToNavigationController() {
    let input = textField.text!
    if let rootVC = navigationController?.viewControllers.first as? MainScreen1 {
        rootVC.input = input
    }
    navigationController?.popToRootViewController(animated: true)
}
  1. I've used CoreData

But here is the difficult part - I've got an email, that all these methods are not good enough and I need to use delegate and closure. I've done delegation and closures before, but when I popToRootViewController delegate method passes nil. Could you at least point where to find info about this?

** ADDED **

There are 2 View Controllers: Initial and Second one. That's what I have in the Initial View Controller:

var secondVC = MainScreen2()

override func viewDidLoad() {
        super.viewDidLoad()     
        secondVC.delegate = self
    }

That's how I push SecondViewController

@objc private func buttonTapped(_ sender: CustomButton) {
        
        let nextViewController = MainScreen2()
        navigationController?.pushViewController(nextViewController, animated: true)
                
    }

In SecondViewController I've got this protocol

protocol PassData {
    func transferData(text: String)
}

Also a delegate:

var delegate: PassData?

This is how I go back to initial view controller

@objc private func buttonTapped(_ sender: CustomButton) {
        
        if let input = textField.text {
            print(input)
            self.delegate?.transferData(text: input)
            self.navigationController?.popToRootViewController(animated: true)
        }
        
    }

Back to the Initial view controller where I've implemented delegate method

extension MainScreen1: PassData {
    func transferData(text: String) {
        print("delegate called")
        label.text = text
        
    }
}

Delegate doesn't get called.

Roma Kavinskyi
  • 268
  • 4
  • 12
  • Did you add a breakpoint to check if your delegate method is being called in your initial view controller? Did you set the delegate as self in your initial view controller? – Mat Jun 23 '20 at 13:30
  • I set delegate to self in the initial view controller, but it doesn't get called – Roma Kavinskyi Jun 23 '20 at 13:58
  • it is wrong the place where you set the delegate. You be must set it in your `buttonTapped` function, not in `viewDidLoad`. That's not the instance you are pushing in the stack – Mat Jun 23 '20 at 14:23

1 Answers1

1

BASED ON YOUR EDIT:

You must set the delegate in buttonTapped

@objc private func buttonTapped(_ sender: CustomButton) {
    
    let nextViewController = MainScreen2()
    nextViewController.delegate = self // HERE WHERE YOU SET THE DELEGATE
    navigationController?.pushViewController(nextViewController, animated: true)
            
}

You can delete the second instance and your code in viewDidLoad. That's not the instance you push.

This should point you in the right direction to use delegation and completion handler.

protocol YourDelegateName {
   func passData(data:YourDataType)
}

class SecondViewController: UIViewController {

  var delegate: YourDelegateName?

  func passDataFromSecondViewController(){

     YourCoreDataClass.shared.getCoreData { (yourStringsArray) in
     self.delegate?.passData(data: yourStringsArray)
     self.navigationController?.popToRootViewController(animated: true)
     }
  }

class InitialViewController: UIViewController, YourDelegateName {


   override func viewDidLoad() {
      super.viewDidLoad()
      // or whenever you instantiate your SecondViewController
      let secondViewController = SecondViewController()
      secondViewController.delegate = self //VERY IMPORTANT, MANY MISS THIS 
      self.navigationController?.pushViewController(createVC, animated: true)
    }


   func passData(data:YourDataType){
       //user your data
   }

}


class YourCoreDataClass: NSObject {
    
     static let  shared = YourCoreDataClass()

     func getCoreData (completion: ([String]) -> ()){
        ........... your code 
         let yourStringsArray = [String]() // let's use as example an array of strings
         //when you got the data your want to pass
         completion(yourStringsArray)
      }
}
Mat
  • 6,236
  • 9
  • 42
  • 55
  • Thanks for your answer! Unfortunately, somewhy the delegate doesn't get called. My implementation is exactly like yours. – Roma Kavinskyi Jun 23 '20 at 13:58
  • are you sure you are using the same instance that gets pushed by the Navigation Controller? Can you post your code? – Mat Jun 23 '20 at 14:02
  • There are only 2 ViewControllers. Initial and Second one. While I'm on the Second View Controller I use the method ` navigationController?.popToRootViewController(animated: true) ` . I believe it is the same instance. – Roma Kavinskyi Jun 23 '20 at 14:06
  • I mean when you push your second view controller? Can you show the part where you set the delegate to self and push it in the Initial? – Mat Jun 23 '20 at 14:07
  • I've added it to the original post – Roma Kavinskyi Jun 23 '20 at 14:21
  • I am glad it worked. Can you please accept the answer. ;) – Mat Jun 23 '20 at 14:34