UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

How to pass data to the parent View from is a child 🙄?

Forums > Swift

Good afternoon. Tell me how to pass data back from the child controller to the parent? ContactListViewController -> SignInViewController

In the presenter, using the closeContactList method, I transfer data.

closeContactList(number: ContactListModel.ViewModel.Phone) 

And trying to process it in the coordinator using the closeContactScene method.

closeContactScene(number: ContactListModel.ViewModel.Phone

But I can’t figure out how to pass the number to showSignInScene?

    func showSignInScene() {
        let assembly = SignInAssembler()
        let singInVC = assembly.configurator(delegate: self)
        guard let render =  singInVC as? ISignInViewLogic else { return }

        render.renderFromContactList(phone: number)
        navigationController.pushViewController(singInVC, animated: true)
    }
import Foundation

protocol IContactListPresenter: AnyObject {
    func present(response: ContactListModel.Response)
    func closeContactList(number: ContactListModel.ViewModel.Phone)
}

final class ContactListPresenter {

    // MARK: - Dependencies
    weak var viewController: IContactListViewLogic?
    var phoneMaskManager: IPhoneMaskManager?

    /// Обработчик закрытия окна, список контактов.
    var closeContactListDelegate: ICloseContactListDelegate?

    // MARK: - Initializator
    internal init(
        phoneMaskManager: IPhoneMaskManager,
        closeContactListDelegate: ICloseContactListDelegate?
    ) {
        self.phoneMaskManager = phoneMaskManager
        self.closeContactListDelegate = closeContactListDelegate
    }
}

extension ContactListPresenter: IContactListPresenter {
    func present(response: ContactListModel.Response) {
        switch response {
        case .success(let contacts):
            let viewModel = contacts.map {
                let currentContact = addMaskPhone(phones: $0.contacts)
                return ContactListDisplay(from: $0, masks: currentContact)
            }
            viewController?.render(contactList: viewModel)
        case .failure(let error):
                closeContactListDelegate?.failure(massage: error.localizedDescription)
        }
    }

    private func addMaskPhone(phones: [String]) -> [ContactListModel.ViewModel.Phone] {
        var numbersWithMask: [ContactListModel.ViewModel.Phone] = []
        if let phoneManager = phoneMaskManager {
            numbersWithMask = phones.map { phone in
                let tempMask = phoneManager.convertInMask(phone: phone)
                return ContactListModel.ViewModel.Phone(phone: phone, maskPhone: tempMask)
            }
        }
        return numbersWithMask
    }

    func closeContactList(number: ContactListModel.ViewModel.Phone) {
        closeContactListDelegate?.closeContactScene(number: number)
    }
}
import UIKit

protocol ISignInCoordinator: ICoordinator {
    func showSignInScene()
}

protocol ISignInSceneDelegate: AnyObject {
    /// Отображение адресной книги телефона.
    func showContactScene()
}

protocol ICloseContactListDelegate: AnyObject {
    /// Закрытие окна отображение список контактов из адресной книги.
    /// - Parameters:
    ///   - number: Возвращает структуру ``Phone``
    func closeContactScene(number: ContactListModel.ViewModel.Phone)
    /// Показ UIAlertView в случае ошибки.
    func failure(massage: String)
}

final class SignInCoordinator: ISignInCoordinator, ISignInSceneDelegate {

    // MARK: - Public properties
    var childCoordinators: [ICoordinator] = []

    // MARK: - Dependencies
    var navigationController: UINavigationController
    var finishDelegate: ICoordinatorFinishDelegate?

    // MARK: - Private properties
    private var number: PhoneNumberModel = PhoneNumberModel(phone: "", maskPhone: "")

    // MARK: - Initializator
    internal init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    // MARK: - Public methods
    func start() {
        showSignInScene()
    }

    func showSignInScene() {
        let assembly = SignInAssembler()
        let singInVC = assembly.configurator(delegate: self)
        guard let render =  singInVC as? ISignInViewLogic else { return }

        render.renderFromContactList(phone: number)
        navigationController.pushViewController(singInVC, animated: true)
    }

    func showContactScene() {
        let assembly = ContactListAssembler()
        let contactListVC = assembly.configurator(handlerCloseContactList: self)
        navigationController.pushViewController(contactListVC, animated: true)
    }
}

extension SignInCoordinator: ICloseContactListDelegate {
    func closeContactScene(number: ContactListModel.ViewModel.Phone) {
        self.number = number
        navigationController.popViewController(animated: true)
    }

    func failure(massage: String) {
        show(typeMassage: .errorBlock(massage: massage))
    }
}

extension SignInCoordinator: ICustomUIAlertProtocol {
    func show(typeMassage: AlertMassageType) {
        let alertVC = CustomUIAlertController(type: typeMassage)
        alertVC.show(typeMassage: typeMassage)
        navigationController.present(alertVC, animated: true)
    }
}

2      

Use delegate pattern in this case. But I guess it's still the same logic in most UIKit based apps.

protocol RequestToParentProtocol {
    func whatDoYouWant(request: String)
}

class Parent: RequestToParentProtocol {
    var name: String
    var request: String

    init(name: String, request: String = "") {
        self.name = name
        self.request = request
    }

    func whatDoYouWant(request: String) {
        self.request = request
    }
}

class Child  {
    var delegate: RequestToParentProtocol?
}

let father = Parent(name: "Father")
let child = Child()

// Do not forget to assign as a delegate

child.delegate = father

child.delegate?.whatDoYouWant(request: "I want to drink!")

father.request

so basically you pass the data from one class to the other up.

or you need it in SwiftUI, as it is not clear what you use...

2      

Good afternoon. I am using the VIP + Coordinator architecture. And trying to pass data from child view to parent view. Using the coordinator - SignInCoordinator, as a link between two UIView.

I tried with delegates but somehow it’s not possible to transfer the data anyway.

GitHub link

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.