Передать данные между контроллерами программно?
Если пользуешься storyboard, тогда передать данные можно через prepareForSegue
Допустим у тебя есть NextViewController с переменной name: Stringclass NextViewController: UIViewController {
    var name: String!
}
и тебе нужно в него передать имя, тогда в prepareForSegue есть два способа детектить переход на NextViewController:
1. Если у нас имеется только один переход на NextViewController или их много с разных кнопок, но данные всегда одинаковыеoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let dest = segue.destination as? NextViewController {
        dest.name = "Jessica"
    }
}
2. Если у нас имеются разные переходы на NextViewController и набор передаваемых данных различаетсяoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let dest = segue.destination as? NextViewController {
        if segue.identifier == "action1" {
            dest.name = "Jessica"
        } else if segue.identifier == "action2" {
            dest.name = "Jessica"
            dest.sex = "female"
        }
    }
}
В случае если программно создаете переход, то еще проще все. Снова два варианта как достучаться до NextViewController:
1. Он находится на storyboardlet dest = storyboard?.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
2. Или он не на storyboard...let dest = NextViewController(nibName:"NextViewController", bundle: nil)
Дальше прикрепляем данныеdest.name = "Jessica"
И два варианта как открыть NextViewController:
1. При наличии navigationController'anavigationController?.pushViewController(dest, animated: true)
2. Просто модальным окномdest.modalPresentationStyle = .fullScreen
dest.modalTransitionStyle = .coverVertical
present(dest, animated: true, completion: nil)
Чтобы обратно из второго в первый данные передавать, можно использовать delegate или notifications.
Если делегатыprotocol NextViewControllerDelegate {
    func callback(_ someString: String)
}

class NextViewController: UIViewController {
    var name: String!
    var delegate: NextViewControllerDelegate?

    func someMethod() {
        delegate?. callback("delegate callback")
    }
}

//Тут контроллер из которого открываем CustomViewController, нам помимо name нужно теперь еще задать delegate=self

class HomeViewController: UIViewController, NextViewControllerDelegate {
   override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dest = segue.destination as? NextViewController {
            dest.name = "Jessica"
            dest.delegate = self
        }
    }

    //MARK: NextViewControllerDelegate
    func callback(_ someString: String) {
        print("got callback with string: \(someString)")
    }
}
Если notificationslet kNotifNextViewControllerCallback = NSNotification.Name(rawValue: "kNotifNextViewControllerCallback")

class NextViewController: UIViewController {
    var name: String!

    func someMethod() {
        NotificationCenter.default.post(name: kNotifNextViewControllerCallback, object: "notification text")
    }
}

//Тут HomeViewController из которого открываем CustomViewController, мы в нем будем слушать kNotifNextViewControllerCallback в метод gotNotification

class HomeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(gotNotification(notification:)), name: kNotifNextViewControllerCallback, object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dest = segue.destination as? NextViewController {
            dest.name = "Jessica"
        }
    }

    //MARK: Notification observer
    func gotNotification(notification: Notification) {
        print("got notification with object: \(notification.object)")
    }
}
Magic:func handleSearch() {
    navigationController?.pushViewController(AlfavitController(with: Magic), animated: true)
}
UPD. Очень смешной прикол
UPD2. 
1. Берем вью контроллер, у которого есть какая-то зависимость (читать как "переменная, которую ему нужно передать")
2. Создаем ему инициализатор с параметром в виде этой зависимости
3. Создаем контроллер с помощью этого инитиализатора
4. Пушим его
5. ???
6. PROFIT