Как можно передать данные между контролерами TabBar?


#1

Как можно передать данные между контролерами TabBar?
На первом контроллере список курсов валют, на втором нужно получить курс по одной из валют. Смотрел уроки, но там везде есть переход между экранами и по индентификатору можно точно зацепится на нужный контроллер.

Сделал проект в упрощенном виде, на первом контроллере ввожу строку и по нажатию кнопки пытаюсь передать текст в label на втором контроллере, но отладка не останавливается на точке останова, как будто не понимает что это именно тот контроллер.


#2

Если через делегат, то наверное примерно так, не проверял)
p.s. Я бы тут использовал нотификацию

protocol DataDelegate: class {
    func data(rate: String)
}

class First: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        (tabBarController as? Tabbar)?.dataDelegate?.data(rate: "f*ck )")
    }
    
}


class Second: UIViewController, DataDelegate {
    func data(rate: String) {
        print("RATE: ", rate)
    }
}



class Tabbar: UITabBarController {
    
    weak var dataDelegate: DataDelegate?
    
    let firstNav = UINavigationController(rootViewController: First())
    
    lazy var secondNav: UINavigationController = {
        let vc = Second()
        self.dataDelegate = vc
        return .init(rootViewController: vc)
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        viewControllers = [firstNav, secondNav]
    }
}

Прикольно, на форуме есть цензура)

protocol DataDelegate: class {
    func data(rate: String)
}

class First: UIViewController {

    weak var delegate: DataDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        delegate?.data(rate: "f*ck )")
    }
    
}


class Second: UIViewController, DataDelegate {
    func data(rate: String) {
        print("RATE: ", rate)
    }
}



class Tabbar: UITabBarController {
    
    let firstNav = UINavigationController(rootViewController: First())
    
    lazy var secondNav: UINavigationController = {
        let vc = Second()
        (firstNav.viewControllers.first as? First)?.delegate = vc
        return .init(rootViewController: vc)
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        viewControllers = [firstNav, secondNav]
    }
}

Ну или так)

protocol DataDelegate: class {
    func data(rate: String)
}

    class First: UIViewController {

        weak var delegate: DataDelegate?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            //зависит от того как устрое у вас tabbar)
        let vc = ((tabBarController?.viewControllers?[1] as? UINavigationController)?.viewControllers.first as? Second)
        delegate = vc
        
        
        delegate?.data(rate: "f*ck )")
    }
    
}


class Second: UIViewController, DataDelegate {
    func data(rate: String) {
        print("RATE: ", rate)
    }
}

Нужно проверить, писал в плейгроунд, может что и не так)


#3
class First: UIViewController {
    
    func post(_ rate: String) {
        NotificationCenter.default.post(name: .init("Rate"), object: rate)
    }
}


class Second: UIViewController {
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        registerNotification()
    }
    
    func registerNotification() {
        NotificationCenter.default.addObserver(self, selector: #selector(handle(_:)), name: .init("Rate"), object: nil)
    }
    
    @objc func handle(_ notification: Notification) {
        print(notification.object as! String)
    }
}


var first = First()
var second = Second()
second.viewDidLoad()

first.post("f*ck")

#4

В данном случае TabBarController уже служит в своем роде делегатом и создавать в нем еще один делегат, это уже лишнее.
Достаточно создать метод для передачи в самом TBC, а так же принимающий метод в самом VC.


#5

Хотел расписать почему нет, но в принципе да)