У меня есть пользователи, которые заполняют некоторую информацию о профиле через текстовые поля (имя, адрес электронной почты и т. д.), которые используются для установки моих значений ProfileContoller.shared.profile. Когда я доберусь до своего навигационного перехода, чтобы передать данные, мой пункт назначенияVC.profile не установит свое значение для объекта отправляющего профиля, и вместо этого я получу ноль.
Мой VC-отправитель встроен в навигационный контроллер, а VC-адрес назначения встроен в контроллер панели вкладок.
// 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 ноль
ProfileController
и ProfileViewController
это одно и то же? Это ошибка написания в приведенном выше фрагменте кода?
Хорошо, есть изображения, связанные выше.
Можете ли вы показать свой код для ProfileController
и ProfileViewController
?
Нет, ProfileController — это контроллер модели, который содержит мой синглтон, а ProfileViewController — это UIViewController.
А вы пробовали po destinationVC
?
Я получаю еще одно нулевое значение, когда захожу в пункт назначенияVC.
@VRAwesome уверен, что я только что добавил это.
didSet
срабатывает, пока ваш vc в segue еще не загружен, поэтому все выходы равны нулю
нужно положить updateViews()
внутрь viewDidLoad
Плюс ваш пункт назначения - tabBar
let tab = segue.destination as! UITabBarController
let destinationVC = tab.viewControllers![2] as! ProfileViewController
спасибо, это я тоже пробовал. когда я открываю профиль после viewDidLoad, я все равно получаю ноль
как вам ориентироваться performSegue
или present
??
Я думаю, что PerformSegue, я не думаю, что использовал настоящее раньше
сделать let destinationVC = segue.destination as! ProfileViewController
и прикрепить краш
SIGABRT — не удалось преобразовать значение типа «UITabBarController» (0x110757300) в «Memic.ProfileViewController» (0x103c810e0). 30.05.2019 13:01:16.666498-0600 Memic[13037:13192113] Не удалось преобразовать значение типа UITabBarController (0x110757300) в Memic.ProfileViewController (0x103c810e0).
Я думал, что это было! Не удалось преобразовать значение типа «UITableViewController» (0x116c5e520) в «Memic.ProfileViewController» (0x10a187108). 30.05.2019 13:16:01.123162-0600 Memic[13320:13200646] Не удалось преобразовать значение типа UITableViewController (0x116c5e520) в Memic.ProfileViewController (0x10a187108).
это должен быть UIViewController, а не TableView
на какой вкладке находится ваш профиль vc внутри вкладки?
Вы не получаете данные в ProfileViewController, потому что конечным контроллером является UITabBarController. Преобразуйте свой оператор из let destinationVC = segue.destination as? ProfileViewController в guard let destinationVC = segue.destination as? ProfileViewController else { return } destinationVC.profile = profile
нет, это не решит проблему, пунктом назначения перехода является tabController в соответствии с ошибкой, а не vc
это третий контроллер, а не первый - я не знаю синтаксиса, но пытаюсь решить
круто, большое спасибо! данные проходят, хотя функция updateViews в целевом виртуальном канале разворачивает ноль, что странно, потому что я могу указать все значения профиля - Неустранимая ошибка: неожиданно найден ноль при неявной распаковке необязательного значения
не используйте didSet
используйте viewDidLoad
и убедитесь, что все розетки подключены и не назначайте их внутри prepare
также
@bhersh90 let tab = segue.destination as! UITabBarController
let destinationVC = tab.viewControllers![2] as! ProfileViewController
. Использование этого уровня развертывания не является предпочтительным, потому что все эти принудительные развертывания и использование магических чисел для оценки значения в массиве, например tab.viewControllers![2]
, могут привести к сбою. Я бы порекомендовал просмотреть ответ, который я разместил ниже один раз.
идеально. Я действительно ценю помощь
@AnkushBhatia, ваш код не имеет смысла, если вы знаете и уверены в чем-то, не о чем беспокоиться !
Спасибо, Анкуш - я переключил их все обратно на опции, и, похоже, все работает хорошо.
@ bhersh90 плохой дизайн - это написание кода, который может привести к проблемам в каком-то крайнем случае в какой-то момент позже, о котором вы не знаете в данный момент времени. Я чувствую, что вы должны писать масштабируемый и динамичный код. Не стесняйтесь следить за обсуждением в ветке ниже.
Я думаю, все, что вам нужно сделать, это вызвать 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
Использование магических чисел не является предпочтительным. Предположим, что какой-то другой разработчик начал работать над этим кодом позже и требует переместить этот контроллер на другую вкладку. Код, который я написал, более динамичен по сравнению с tab.viewControllers![2] as! ProfileViewController
Я почти уверен, что это приведет к сбою, и я не большой поклонник магических чисел и принудительной развертки. Я не могу рисковать, чтобы сделать эту ошибку ни в одном продукте, который я разрабатываю. Я надеюсь, что в моем объяснении достаточно контекста, чтобы заявить, что приведенный выше код более динамичен и масштабируем. @ш-хан
нет необходимости усложнять код для будущих соображений, что, если имя vc изменится, это пойдет в масштабе нового рефакторинга кода
Это было предложение следовать хорошему подходу, который я чувствую. Это зависит от вас, в конце концов, вы хотите следовать или нет. Мой ответ начинался с You can use below code to safely pass data to the ProfileViewController
. Вы можете обратиться к любым рекомендациям по кодированию, я думаю, что все утверждают, что нужно использовать необязательную привязку вместо принудительной развертки и избегать использования магических чисел.
Разместите объявление о переходе на раскадровке (экран печати). Покажите контроллер представления вашего инспектора атрибутов