Как передавать данные с контроллера модального просмотра обратно при увольнении

Я выполнил инструкции здесь, но я до сих пор не уверен в этой части:

modalVC.delegate=self;
        self.presentViewController(modalVC, animated: true, completion: nil) 

Я попытался создать экземпляр контроллера представления программно, но все же безрезультатно.

здесь мой код для отклонения модального контроллера:

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true) { 
            //
        }
    }

Я использую раскадровку, чтобы перейти с модальным видом.

Это данные, которые я хочу передать обратно в родительский контроллер представления:

var typeState = "top"
 var categoryState = "casual"

Какие два значения String.

Изменить:

Я попытался передать данные с контроллера модального представления, как показано:

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true, completion: nil)
        delegate?.sendValue(value: "success")
        if let presenter = presentingViewController as? OOTDListViewController {
            presenter.receivedValue = "test"
        }
    }

тогда как на контроллере родительского представления я сделал следующее:

func sendValue(value: NSString) {
        receivedValue = value as String
    }
  @IBAction func printReceivedValue(_ sender: UIButton) {
        print(receivedValue)
    }

Я все равно не получаю никакого значения, когда нажимаю кнопку печати.

Модальный контроллер:

protocol ModalViewControllerDelegate
{
    func sendData(typeState: String, categoryState: String)
}

var delegate:ModalViewControllerDelegate!

var typeState = "top"
var categoryState = "casual"
@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true, completion: nil)
        delegate?.sendData(typeState: typeState as String, categoryState: categoryState as String)

    }

Контроллер родительского контроля:

class parentViewController: UICollectionViewController, ModalViewControllerDelegate {

var typeState: String?
var categoryState: String?
func sendData(typeState: String, categoryState: String) {
        self.typeState = typeState as String
        self.categoryState = categoryState as String
    }
 @IBAction func printReceivedValue(_ sender: UIButton) {
     print(typeState)
 }

Изменить:

Здесь мой новый код без использования метода делегата:

Модальный контроллер:

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
        self.dismiss(animated: true, completion: nil)
        if let presenter = presentingViewController as? OOTDListViewController {
            presenter.typeState = typeState
            presenter.categoryState = categoryState
        }
    }

OOTDListViewController:

@IBAction func presentModalView(_ sender: UIBarButtonItem) {
        let modalView = storyboard?.instantiateViewController(withIdentifier: "filterViewController") as! ModalViewController
        let navModalView: UINavigationController = UINavigationController(rootViewController: modalView)
        self.present(navModalView, animated: true, completion: nil)
    }
@IBAction func printValue(_ sender: UIButton) {
        print(typeState)
        print(categoryState)
    }

Ответ 1

В зависимости от данных, которые вы хотите передать, вы можете создать свойство в представлении контроллера представления, которое вы можете установить при отклонении модального контроллера представления, чтобы вы могли освободить себя от делегата.

Например, у вас есть ContactsViewController, удерживая свойство var contacts: [Contact] = []. Когда вы хотите создать новый контакт, вы представляете контроллер модального представления с разными значениями, необходимыми для создания нового объекта Contact. Когда вы закончите и хотите отклонить контроллер вида, вы вызываете функцию так же, как и в вашем коде, но устанавливаете свойство в ContactsViewController. Он будет выглядеть примерно так:

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
    if let presenter = presentingViewController as? ContactsViewController {
        presenter.contacts.append(newContact)
    }
    dismiss(animated: true, completion: nil)
}

EDIT:

Если вы не хотите использовать делегат, вот как вы это сделаете:

В OOTDListViewController:

var testValue: String = ""

@IBAction func printReceivedValue(_ sender: UIButton) {
    print(testValue)
}

В вашем модульном контроллере просмотра (я назову его PresentedViewController):

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
    // if your OOTDListViewController is part of a UINavigationController stack, this check will probably fail. 
    // you need to put a breakpoint here and check if the presentingViewController is actually a UINavigationController.
    // in that case, you will need to access the viewControllers variable and find your OOTDListViewController
    if let presenter = presentingViewController as? OOTDListViewController {
        presenter.testValue = "Test"
    }
    dismiss(animated: true, completion: nil)
}

Если вы хотите использовать делегат, вот как это сделать:

В вашем OOTDListViewController:

protocol ModalDelegate {
func changeValue(value: String)
}

class OOTDListViewController: ModalDelegate {

var testValue: String = ""
@IBAction func presentViewController() {
    // here, you either create a new instance of the ViewController by initializing it, or you instantiate it using a storyboard. 
    // for simplicity, I'll use the first way
    // in any case, you cannot use a storyboard segue directly, bevause you need access to the reference of the presentedViewController object
    let presentedVC = PresentedViewController() 
    presentedVC.delegate = self
    present(presentedVC, animated: true, completion: nil)
}

func changeValue(value: String) {
     testValue = value
     print(testValue)
}

}

В вашем PresentedViewController:

class PresentedViewController {
    var delegate: ModalDelegate? 
    var testValue: String = ""

    @IBAction func dismissViewController(_ sender: UIBarButtonItem) {
       if let delegate = self.delegate {
            delegate.changeValue(testValue)
        }
        dismiss(animated: true, completion: nil)
    }

}

Ответ 2

Вам нужно вызвать метод делегата в методе dismissViewController

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
        delegate?.sendData(typeState: "top", categoryState: "casual")
        self.dismiss(animated: true) { 
            //
        }
 }

в вашем классе Modal ViewController создайте делегат

var delegate: MyProtocol?

создать протокол с именем метода sendData в MyProtocol и в вашем представленииViewController, где вы назначаете делегат, реализовать метод MyProtocol

protocol MyProtocol: class {
    func sendData(typeState: String, categoryState: String)
}

class ViewController: UIViewController, MyProtocol {
    var typeState: String?
    var categoryState: String?

    func sendData(typeState: String, categoryState: String) {
       self.typeState = typeState
       self.categoryState = categoryState
    }
 }

Ответ 3

Я использую табуляцию, поэтому рабочий код ниже

            if let tabBar = self.presentingViewController as? UITabBarController {
            let homeNavigationViewController = tabBar.viewControllers![0] as? UINavigationController
            let homeViewController = homeNavigationViewController?.topViewController as! HomeController
            homeViewController._transferedLocationID = self.editingLocationID!
        }

Ответ 4

Если вы используете навигационный контроллер, вам сначала нужно взять UINavigation Controller, а затем получить правильный ViewController из стека Navigation Controller.

Вот как мой код выглядел в таком случае.

@IBAction func dismissViewController(_ sender: UIBarButtonItem) {
    if let navController = presentingViewController as? UINavigationController {
       let presenter = navController.topViewController as! OOTDListViewController
        presenter.testValue = "Test"
    }
    dismiss(animated: true, completion: nil)
}