Swift 4.2: не удается заставить работать простой протокол делегата

YouTube Скриншот моего рабочего процесса

Фирствиевконтроллер

import UIKit

class FirstViewController: UIViewController {
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        let secondViewController = SecondViewController()
        secondViewController.delegate = self
    }
}

extension FirstViewController: DataEnteredDelegate {
    func userDidEnterInformation(info: String) {
        label.text = info
        print("label changed")
    }
}

Секондвиевконтроллер

import UIKit

protocol DataEnteredDelegate: class {
    func userDidEnterInformation(info: String)
}

class SecondViewController: UIViewController {
    weak var delegate: DataEnteredDelegate? = nil

    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(_ sender: UIButton) {
        print("button tapped")
        delegate?.userDidEnterInformation(info: textField.text!)
    }
}

Вы не реализовали методы протокола

Parth Dhorda 29.01.2019 13:45

сначала удалите as! DataEnteredDelegate

SPatel 29.01.2019 13:45

куда вы нажали второй контроллер представления?

Ratul Sharker 29.01.2019 13:45
stackoverflow.com/a/37203430/6630644
SPatel 29.01.2019 13:49

Возможный дубликат Передача данных между двумя ViewControllers (делегат) - Swift

Galo Torres Sevilla 29.01.2019 13:56

Возможный дубликат Примеры делегатов в Swift

Mohmmad S 29.01.2019 14:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
388
9

Ответы 9

Проверьте это и обновите.

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!

    func userDidEnterInformation(info: String) {
        label.text = info
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let secondViewController = SecondViewController()
        secondViewController.delegate = self 
    }
}

большое спасибо! я вижу, что изначально пропустил DataEnteredDelegate как суперкласс. я исправил это, но это не работает (см. обновленный пост)

Amanda Garcia 29.01.2019 15:12

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

class FirstViewController: UIViewController, DataEnteredDelegate {
...
}

Причина в том, что первый контроллер представления не реализовал протокол, поэтому приведение не произошло.

Спасибо!! я пропустил это, исправил, но это все еще не работает (см. обновленный пост)

Amanda Garcia 29.01.2019 15:06

Используйте приведенный ниже код для контроллера FirstView.

import UIKit

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!

    func userDidEnterInformation(info: String) {
        label.text = info
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let secondViewController = SecondViewController()
        secondViewController.delegate = self
    }

    func userDidEnterInformation(info: String){
      // do your stuff here
    }

}

большое спасибо! я вижу, что изначально пропустил DataEnteredDelegate как суперкласс. я исправил это, но это не работает (см. обновленный пост)

Amanda Garcia 29.01.2019 15:12

Внедрите свой протокол в свой первый контроллер представления. Хорошей практикой является расширение контроллера, а затем добавление методов делегата протокола к этому расширению.

extension FirstViewController: DataEnteredDelegate {
    func userDidEnterInformation(info: String) {
        ...
    }
}

Далее, второй контроллер представления, делегат которого вы устанавливаете, вероятно, не является контроллером, который вы представляете позже. Чтобы правильно установить делегата, установите делегат контроллера, который будет представлен. Если вы используете переходы, переопределите prepare(for:sender:) и установите делегата назначения пониженного перехода. Если вы представляете контроллер представления вручную или нажимаете его, установите делегата этого контроллера, который вы представляете/нажимаете.

большое вам спасибо! Я переместил фрагмент кода в расширение и исправил другие ошибки. Я не нажимаю и не перехожу (см. обновленное видео), я просто хочу обновить первый viewController вручную со второго.

Amanda Garcia 29.01.2019 15:10

@AmandaGarcia прочитайте ответ более внимательно. Я описал, почему ваш код не работает

Robert Dresler 29.01.2019 19:36

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

попробуй настроить так:

    weak var delegate: DataEnteredDelegate? = FirstViewController.self as! DataEnteredDelegate

Помимо отсутствующего принятия делегата

class FirstViewController: UIViewController, DataEnteredDelegate {

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

Линия

let secondViewController = SecondViewController()

создает новый экземпляр SecondViewController, который является нет экземпляром в раскадровке, и все выходы подключены нет.

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

Примечание:

С точки зрения протокола/делегата Swift для обмена данными между контроллерами вполне достаточно объективный.
. Закрытие обратного вызова более легкое и быстрее.

Прямой блок Second ViewController здесь неприемлем. Кроме того, после двух шагов второй ViewController будет выпущен и не будет существовать.

   override func viewDidLoad() {
    super.viewDidLoad()

    let secondViewController = SecondViewController() // Not the right way to initialize!
    secondViewController.delegate = self. //secondViewController  will be released!
    }

Проблема в том, что вы создаете новый SecondViewController вместо фактического, используемого панелью вкладок. Вам нужно получить доступ ко второму контроллеру представления, который используется UITabBarController, вместо выделения нового экземпляра, для этого измените свою реализацию viewDidLoad на:

override func viewDidLoad() {
    super.viewDidLoad()
    let secondViewController      = self.tabBarController?.viewControllers?.last as? SecondViewController
    secondViewController.delegate = self
}

Ваш rootViewController UIWndow - это UITabBarController, который виден по ссылке на видео YouTube, которой вы делитесь, поэтому вам нужно получить SecountViewController из этого места, используя этот фрагмент кода.

class FirstViewController: UIViewController {

@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let rootController = appDelegate.window?.rootViewController as! UITabBarController
    if let viewControllers = rootController.viewControllers {
        if viewControllers.count > 0 {
            if let secondViewController = viewControllers[1] as? SecondViewController {
                secondViewController.delegate = self
            }
        }
    }
}}

Так что ваш делегат не будет нулевым.

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

// you have nil refrence to delegate check it here
if (self.delegate != nil) {
    self.delegate?.userDidEnterInformation(info: textField.text ?? "")
}

надеюсь, это поможет.

Другие вопросы по теме