Swift: мой переход в конечный пункт назначения показывает ноль

У меня есть пользователи, которые заполняют некоторую информацию о профиле через текстовые поля (имя, адрес электронной почты и т. д.), которые используются для установки моих значений ProfileContoller.shared.profile. Когда я доберусь до своего навигационного перехода, чтобы передать данные, мой пункт назначенияVC.profile не установит свое значение для объекта отправляющего профиля, и вместо этого я получу ноль.

Мой VC-отправитель встроен в навигационный контроллер, а VC-адрес назначения встроен в контроллер панели вкладок.

Перейти к отправке VC

Инспектор атрибутов SendingVC

Пункт назначенияВК

// Sending View Controller: 
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let profile = ProfileController.shared.profile else { return }
    if segue.identifier == "signUpMemicTBC" {
        let destinationVC = segue.destination as? ProfileViewController
        destinationVC?.profile = profile

// Receiving ProfileViewController:
class ProfileViewController: UIViewController {

    // MARK: - IBOutlets
    @IBOutlet weak var fullNameLabel: UILabel!
    @IBOutlet weak var usernameLabel: UILabel!
    @IBOutlet weak var emailLabel: UILabel!

    // MARK: - Landing Pad
    var profile : Profile? {
        didSet {
            updateViews()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        updateViews()
    }

    func updateViews () {
        guard let profile = profile else { return }
        fullNameLabel.text = profile.firstName + " " + profile.lastName
        usernameLabel.text = profile.username
        emailLabel.text = profile.email
    }
}

// ProfileController:
class ProfileController {

    // MARK: - Properties
    var profile : Profile?

    // MARK: - Singleton
    static let shared = ProfileController()

}

Мой отправляющий объект имеет данные: (lldb) po профиль Профиль: 0x600000c873c0

Целевой объект неожиданно равен нулю: (lldb) по адресу VC?.profile ноль

Разместите объявление о переходе на раскадровке (экран печати). Покажите контроллер представления вашего инспектора атрибутов

Augusto 30.05.2019 20:03

ProfileController и ProfileViewController это одно и то же? Это ошибка написания в приведенном выше фрагменте кода?

VRAwesome 30.05.2019 20:35

Хорошо, есть изображения, связанные выше.

bhersh90 30.05.2019 20:35

Можете ли вы показать свой код для ProfileController и ProfileViewController?

VRAwesome 30.05.2019 20:35

Нет, ProfileController — это контроллер модели, который содержит мой синглтон, а ProfileViewController — это UIViewController.

bhersh90 30.05.2019 20:37

А вы пробовали po destinationVC?

VRAwesome 30.05.2019 20:40

Я получаю еще одно нулевое значение, когда захожу в пункт назначенияVC.

bhersh90 30.05.2019 20:45

@VRAwesome уверен, что я только что добавил это.

bhersh90 30.05.2019 20:46
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
131
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

didSet срабатывает, пока ваш vc в segue еще не загружен, поэтому все выходы равны нулю

нужно положить updateViews() внутрь viewDidLoad


Плюс ваш пункт назначения - tabBar

let tab = segue.destination as! UITabBarController
let destinationVC = tab.viewControllers![2] as! ProfileViewController

спасибо, это я тоже пробовал. когда я открываю профиль после viewDidLoad, я все равно получаю ноль

bhersh90 30.05.2019 20:26

как вам ориентироваться performSegue или present ??

Sh_Khan 30.05.2019 20:43

Я думаю, что PerformSegue, я не думаю, что использовал настоящее раньше

bhersh90 30.05.2019 20:53

сделать let destinationVC = segue.destination as! ProfileViewController и прикрепить краш

Sh_Khan 30.05.2019 20:54

SIGABRT — не удалось преобразовать значение типа «UITabBarController» (0x110757300) в «Memic.ProfileViewController» (0x103c810e0). 30.05.2019 13:01:16.666498-0600 Memic[13037:13192113] Не удалось преобразовать значение типа UITabBarController (0x110757300) в Memic.ProfileViewController (0x103c810e0).

bhersh90 30.05.2019 21:02

Я думал, что это было! Не удалось преобразовать значение типа «UITableViewController» (0x116c5e520) в «Memic.ProfileViewController» (0x10a187108). 30.05.2019 13:16:01.123162-0600 Memic[13320:13200646] Не удалось преобразовать значение типа UITableViewController (0x116c5e520) в Memic.ProfileViewController (0x10a187108).

bhersh90 30.05.2019 21:17

это должен быть UIViewController, а не TableView

bhersh90 30.05.2019 21:18

на какой вкладке находится ваш профиль vc внутри вкладки?

Sh_Khan 30.05.2019 21:20

Вы не получаете данные в ProfileViewController, потому что конечным контроллером является UITabBarController. Преобразуйте свой оператор из let destinationVC = segue.destination as? ProfileViewController в guard let destinationVC = segue.destination as? ProfileViewController else { return } destinationVC.profile = profile

Ankush Bhatia 30.05.2019 21:21

нет, это не решит проблему, пунктом назначения перехода является tabController в соответствии с ошибкой, а не vc

Sh_Khan 30.05.2019 21:22

это третий контроллер, а не первый - я не знаю синтаксиса, но пытаюсь решить

bhersh90 30.05.2019 21:24

круто, большое спасибо! данные проходят, хотя функция updateViews в целевом виртуальном канале разворачивает ноль, что странно, потому что я могу указать все значения профиля - Неустранимая ошибка: неожиданно найден ноль при неявной распаковке необязательного значения

bhersh90 30.05.2019 21:33

не используйте didSet используйте viewDidLoad и убедитесь, что все розетки подключены и не назначайте их внутри prepare также

Sh_Khan 30.05.2019 21:34

@bhersh90 let tab = segue.destination as! UITabBarControllerlet destinationVC = tab.viewControllers![2] as! ProfileViewController. Использование этого уровня развертывания не является предпочтительным, потому что все эти принудительные развертывания и использование магических чисел для оценки значения в массиве, например tab.viewControllers![2], могут привести к сбою. Я бы порекомендовал просмотреть ответ, который я разместил ниже один раз.

Ankush Bhatia 30.05.2019 21:43

идеально. Я действительно ценю помощь

bhersh90 30.05.2019 21:44

@AnkushBhatia, ваш код не имеет смысла, если вы знаете и уверены в чем-то, не о чем беспокоиться !

Sh_Khan 30.05.2019 21:45

Спасибо, Анкуш - я переключил их все обратно на опции, и, похоже, все работает хорошо.

bhersh90 30.05.2019 21:47

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

Ankush Bhatia 30.05.2019 22:51

Я думаю, все, что вам нужно сделать, это вызвать updateViews() в основной теме.

didSet {
        print("did set profile called")
        DispatchQueue.main.async{[weak self] in
            guard let self = self else {
                return
            }
            self.updateViews()
        }
    }

Другим вариантом было бы обновить просмотры в viewDidLoad()

override func viewDidLoad() {
    if let prof = self.profile {
        self.updateViews()
    }
}

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

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let profile = ProfileController.shared.profile else { return }
        if segue.identifier == "signUpMemicTBC" {
            guard let tabBarController = segue.destination as? UITabBarController else { return }
            guard let profileController = tabBarController.viewControllers?.index(at: 2) as? ProfileViewController else {
                return
            }
            profileController.profile = profile
        }
    }

это first(where: { $0 is ProfileViewController }) as? ProfileViewController не имеет смысла, это должен быть поиск vc, я уверен, что это индекс 2

Sh_Khan 30.05.2019 21:46

Использование магических чисел не является предпочтительным. Предположим, что какой-то другой разработчик начал работать над этим кодом позже и требует переместить этот контроллер на другую вкладку. Код, который я написал, более динамичен по сравнению с tab.viewControllers![2] as! ProfileViewController Я почти уверен, что это приведет к сбою, и я не большой поклонник магических чисел и принудительной развертки. Я не могу рисковать, чтобы сделать эту ошибку ни в одном продукте, который я разрабатываю. Я надеюсь, что в моем объяснении достаточно контекста, чтобы заявить, что приведенный выше код более динамичен и масштабируем. @ш-хан

Ankush Bhatia 30.05.2019 22:48

нет необходимости усложнять код для будущих соображений, что, если имя vc изменится, это пойдет в масштабе нового рефакторинга кода

Sh_Khan 30.05.2019 22:58

Это было предложение следовать хорошему подходу, который я чувствую. Это зависит от вас, в конце концов, вы хотите следовать или нет. Мой ответ начинался с You can use below code to safely pass data to the ProfileViewController. Вы можете обратиться к любым рекомендациям по кодированию, я думаю, что все утверждают, что нужно использовать необязательную привязку вместо принудительной развертки и избегать использования магических чисел.

Ankush Bhatia 30.05.2019 23:01

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