Передача данных с использованием делегатов - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь передать данные между A & C, где A - первый контроллер, а C - третий контроллер. Теперь я знаю, как передавать данные из A в B & B в A, где вы создаете протокол в B и создаете делегата внутри контроллера представления. Это выглядит примерно так.

Контроллер

class AController: UIViewController, BControllerDelegate {
  func bControllerButtonPress() {
    view.backgroundColor = .red
  }

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ShowBController" {
        let vc = segue.destination as! BController
        vc.delegate = self
    }
  }

  @IBAction func showBController() {
    performSegue(withIdentifier: "ShowBController", sender: nil)
  }
}

B Контроллер

protocol BControllerDelegate {
  func bControllerButtonPress()
}

class BController: UIViewController {
  var delegate: BControllerDelegate?

  @IBAction func buttonPress() {
    delegate?.bControllerButtonPress()
    self.dismiss(animated: true, completion: nil)
  }
} 

Теперь, как бы я сделал это с C-контроллером или даже D-контроллером. Потому что у меня есть контроллер навигации, где в контроллере C я создаю новый элемент и попадаю в корневой контроллер вида. Тогда я хотел бы изменить пользовательский интерфейс, но не могу понять это. Буду очень признателен за помощь.

Более подробное объяснение

Контроллер A, контроллер входа в систему, на котором есть кнопка регистрации, которая ведет меня к контроллеру B. Контроллер B, контроллер электронной почты. Контроллер C, имя пользователя / имя контроллера. Контроллер D, контроллер паролей. Таким образом, от контроллера B я передаю электронное письмо контроллеру C и так далее до контроллера D. Именно здесь я создаю нового пользователя. Когда новый пользователь создается в Контроллере D, я выскакиваю к корневому представлению контроллера. Тогда я хотел бы выполнить переход к контроллеру E из контроллера A, как только новый пользователь будет создан в контроллере D. Все контроллеры A, B, C, D находятся в одном навигационном контроллере.

Итак, глядя на ответы @bsod и @Caleb, кажется, что я передаю делегат или модель данных между контроллерами A-B-C-D?

Ответы [ 3 ]

0 голосов
/ 13 января 2019

Теперь, как бы я сделал это с контроллером C или даже контроллером D.

Это хорошая причина для организации вашего приложения на основе модели данных . Делегат приложения или контроллер первого представления могут создать модель, которая должна содержать данные и бизнес-логику для приложения. Каждый контроллер представления передает ссылку на модель любым другим созданным им контроллерам представления, и тогда вам не нужно сильно беспокоиться о передаче данных между контроллерами представления. Если ваш контроллер представления C или D вносит некоторые изменения в модель, их не нужно явно возвращать в A ... A просто автоматически получает обновленные данные благодаря общению с той же моделью данных, которую использует C или D .

Вот конкретный пример. Допустим, вы создаете органайзер для продавцов. Таким образом, ваша модель данных может называться OrganizerModel, и она будет включать список customers. Вы можете нажать на кнопку, чтобы увидеть все местоположения клиентов на карте, а затем вы можете нажать на определенное местоположение на карте, чтобы просмотреть и изменить данные клиентов. Итак, как эти изменения должны быть доведены до остальной части приложения? Давайте представим, что есть MainViewController, который показывает основной вид приложения и позволяет получить доступ к списку клиентов, списку поставщиков, каталогу продуктов, календарю и т. Д. Когда вы нажимаете кнопку, чтобы просмотреть список клиентов, MainViewController переходит к CustomerListViewController, а в prepare(for:sender:) он делает что-то вроде:

guard let customerListController = segue.destinationController as CustomerListViewController else {
   //...
}
customerListController.customerList = self.organizerModel.customerList

Так что теперь контроллер списка клиентов имеет доступ к списку клиентов, и это все, что ему нужно для своей работы. Оттуда пользователь может нажать кнопку, чтобы увидеть всех клиентов на карте, и когда это произойдет, CustomerListViewController перейдет к CustomerMapViewController, снова сделав что-то вроде:

guard let customerMapController = segue.destinationController as CustomerMapViewController else {
   //...
}
customerMapController.customerList = self.customerList

Таким образом, CustomerMapViewController показывает карту, включающую маленькие значки для каждого клиента, и когда пользователь нажимает на одну из них, он переходит к CustomerViewController, которому для выполнения всего, что он делает, требуется только одна запись клиента:

guard let customerController = segue.destinationController as CustomerProfileViewController else {
   //...
}
customerController.customer = self.customerList[selectedCustomer]

Теперь у нас есть ситуация, подобная вашему A->B->C->D случаю, когда контроллер представления в нескольких шагах от первого изменяет некоторые данные. Но когда CustomerProfileViewController вносит некоторые изменения в customer, нет необходимости отправлять эту информацию обратно в MainViewController, потому что MainViewController и CustomerProfileViewController используют одни и те же данные; это customer является частью общей модели, которую использует MainViewController.

0 голосов
/ 13 января 2019

Строго, чтобы ответить на ваш вопрос, делегаты могут быть связаны с протоколом или без него. С протоколом:

protocol DoSomething: AnyObject {
    func doSomething()
}
class VCA: UIViewController, DoSomething {
    func doSomething() {
        print("do something")
    }
    func push() {
        let b = VCB()
        b.delegate = self
    }
}
class VCB: UIViewController, DoSomething {
    weak var delegate: DoSomething?
    func doSomething() {
        delegate?.doSomething()
    }
    func push() {
        let c = VCC()
        c.delegate = delegate // instead of declaring self as the delegate
                              // you can declare the delegate (which is VCA)
    }
}
class VCC: UIViewController {
    weak var delegate: DoSomething?
    func doSomething() {
        delegate?.doSomething()
    }
}

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

class VCA: UIViewController {
    func doSomething() {
        print("do something")
    }
    func push() {
        let b = VCB()
        b.delegate = self
    }
}
class VCB: UIViewController {
    weak var delegate: VCA?
    func push() {
        let c = VCC()
        c.delegate = delegate
    }
}
class VCC: UIViewController {
    weak var delegate: VCA?
    func doSomething() {
        delegate?.doSomething()
    }
}

Тщательно продумайте, как вы разрабатываете свои контроллеры представлений и передаете данные, поскольку шаблон делегата - не единственный вариант, однако это основа.

0 голосов
/ 13 января 2019

У вас может быть другая возможность сделать это, Первый: вы должны создать своих делегатов от A до B, а затем снова от B до C. (Если вы не хотите, чтобы ваш контроллер представления B появлялся, а анимация ложная предложила бы)

Или вы можете выбрать создание шины уведомлений между контроллерами ciew. Для него можно использовать метод «NotificationCenter». Где вы определяете в нем одного и того же наблюдателя и получателя, вы получите контроль класса, в котором вы определили получателя этого уведомления.

Пожалуйста, удалите все уведомления наблюдателя при нажатии нового контроллера представления.

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