Список загрузки в базе данных Firebase и Firestore ⇐ IOS
-
Anonymous
Список загрузки в базе данных Firebase и Firestore
Я столкнулся с проблемой в своем приложении, которую не могу решить. В моем проекте есть разные представления, в которых пользователь может выбрать еду для списка покупок. Когда пользователь выбрал по категориям все элементы для добавления в список, они сохраняются и отображаются в firstView, где расположены все списки, сохраненные пользователями. Моя проблема в том, что я пытаюсь увидеть в списке только те элементы, которые были загружены, и теперь я сталкиваюсь с этой проблемой как с циклом, потому что, когда я нажимаю на ячейки, эти элементы смешиваются и отображаются в разных списках, где они были. не загружен. Я пытался добавить переменную с уникальным идентификатором для элемента или списка, чтобы избежать этого, но это было невозможно, я ошибся в чем-то другом. Могу ли я получить некоторую помощь, пожалуйста?
импортировать UIKit импортировать Firebase импортировать FirebaseAuth импортировать базу данных FirebaseDatabase импортировать локальную аутентификацию класс FirstView: UIViewController, UITableViewDelegate, UITableViewDataSource { func DidSaveNewList (listName: String, items: [ListTextField]) { охранник !listName.isEmpty еще { print("Номер списка не может быть удален.") print("Сохраняем новый список с номером: \(listName) и элементами: \(items)") возвращаться } пусть listData: [Строка: Любой] = [ "имя_списка": имя_списка, "предметы": items.map { $0.toAnyObject() } ] let userRef = Database.database().reference(withPath: "userLists/\(Auth.auth().currentUser!.uid)/\(listName)") userRef.setValue(listData) {ошибка, _ в если пусть ошибка = ошибка { print("Не удалось сохранить данные: \(ошибка).") } еще { print("Данные успешно сохранены!") self.lists[listName] = элементы self.firstTableView.reloadData() } } } списки переменных: [String: [ListTextField]] = [:] var listName: String? элементы var: [ListTextField]? переопределить func viewWillAppear(_animated: Bool) { super.viewWillAppear(анимированный) если пусть пользователь = Auth.auth().currentUser { loadListsFromFirebase (uid: user.uid) } } переопределить функцию viewDidLoad() { супер.viewDidLoad() настройкаUI() } деинит { NotificationCenter.default.removeObserver(self) } func newListSaved(listName: String, items: [Product]) { let ConvertItems = items.map {продукт в ListTextField(id: product.id, заголовок: product.name_es, подзаголовок: товар.категория, isChecked: product.isChecked) } print("Новый список охраняемых номеров: \(listName) и продуктов: \(items)") print("Преобразованные элементы: \(convertedItems)") списки[listName] = конвертированные элементы firstTableView.reloadData() } частная функция loadListsFromFirebase (uid: String) { print("Начало загрузкиListsFromFirebase для пользователя \(uid)") let ref = Database.database().reference().child("userLists").child(uid) ref.observe(.value) { [слабый собственный] снимок в print("Наблюдение за событиями в Firebase") var newLists: [String: [ListTextField]] = [:] для ребенка в snapshot.children { если let childSnapshot = child as? DataSnapshot, пусть значение = childSnapshot.value как? [Строка: любая] { пусть listName = childSnapshot.key print("Обработка списка с номером: \(listName)") если let itemsData = value["items"] как? [[Строка: Любая]] { элементы var: [ListTextField] = [] для itemData в itemsData { если пусть id = itemData["id"] как? Нить, let title = (itemData["name_es"] as? String) ?? (itemData["title"] как? Строка), let subtitle = (itemData["category"] as? String) ?? (itemData["subtitle"] как? Строка), пусть isChecked = itemData["isChecked"] как? Бул { пусть listItem = ListTextField (id: id, title: title, subtitle: subtitle, isChecked: isChecked) items.append(listItem) print("Элемент, объединенный в список \(listName): \(listItem)") } } newLists[listName] = элементы } Еще, если let itemsData = value["items"] as? [Строка: [Строка: Любой]], letnestedItems = itemsData["items"] { элементы var: [ListTextField] = [] for (id, itemData) вnestedItems { если пусть itemData = itemData как? [Строка: любая], let title = itemData["title"] как? Нить, let subtitle = itemData["subtitle"] как? Нить, пусть isChecked = itemData["isChecked"] как? Бул { пусть listItem = ListTextField (id: id, title: title, subtitle: subtitle, isChecked: isChecked) items.append(listItem) print("Объединенный элемент в список \(listName): \(Элемент списка)") } } newLists[listName] = элементы } } } self?.lists = новые списки DispatchQueue.main.async { print("Вернуть данные таблицы") сам?.firstTableView.reloadData() } } } // Расширение класса: func tableView (_ tableView: UITableView, раздел NumberOfRowsInSection: Int) -> Int { print("Обновлен номер файла в разделе: \(section), count: \(lists.count)") вернуть lists.keys.count } func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("Откройте папку indexPath: \(indexPath), listas: \(lists)") Guard let Cell = tableView.dequeueReusableCell (withIdentifier: FirstCell.firstIdentifier, for: indexPath) как? FirstCell еще { FatalError("Ячейка, исключенная из очереди, не является экземпляром FirstCell.") } пусть listName = Array(lists.keys).sorted()[indexPath.row] cell.mainLabel.text = имя_списка.заглавными буквами cell.layer.cornerRadius = 10 cell.clipsToBounds = правда print("Создание списка с именем: \(listName)") возвратная ячейка } func tableView (_ tableView: UITableView, TrailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> Конфигурация UISwipeActions? { let deleteAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Eliminar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Выбрать элемент локального списка пусть listKey = Array(self.lists.keys)[indexPath.row] self.lists.removeValue(forKey: listKey) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) завершение (правда) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: { _ in завершение (ложь) })) self.present(предупреждение, анимированное: true) } вернуть UISwipeActionsConfiguration (действия: [deleteAction]) } func tableView (_ tableView: UITableView, DidSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, анимированный: true) пусть selectedListName = Array(lists.keys)[indexPath.row] пусть selectedListItems = списки[selectedListName] пусть раскадровка = UISstoryboard (имя: «Основной», пакет: ноль) если позволить newListView = Storyboard.instantiateViewController(withIdentifier: "NewListView") как? НьюЛистВью { newListView.listName = выбранноеИмяСписка newListView.items = selectedListItems ?? [] NavigationController?.pushViewController(newListView, анимированный: true) } еще { print("Невозможно создать NewListView") } } } Второе представление для отображения элементов в списке:
импортировать UIKit импортировать Firebase импортировать FirebaseAuth импортировать базу данных FirebaseDatabase класс NewListView: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet слабая вар addItemTextFieldNew: UITextField! @IBOutlet слабая переменная showListButton: UIButton! @IBOutlet слабая переменная saveListButton: UIButton! @IBOutlet слабая переменная plusButtonAdd: UIButton! @IBOutlet слабая вар newListTableView: UITableView! частный пусть градиентный слой = CAGradientLayer() частная база данных let = Database.database().reference(withPath: "iFoodList") частный список переменныхRef: DatabaseReference? var listName: String? элементы var: [ListTextField] = [] списки переменных: [String: [ListTextField]] = [:] переопределить функцию viewDidLoad() { супер.viewDidLoad() охранник пусть tableView = newListTableView еще {возвращение} tableView.delegate = сам tableView.dataSource = сам tableView.register(UINib(nibName: "NewListCell", пакет: ноль), forCellReuseIdentifier: NewListCell.reuseIdentifier) tableView.estimatedRowHeight = 66 tableView.rowHeight = UITableView.automaticDimension self.title = имя_списка ?? «Новый список» view.backgroundColor = .white настроитьUI() loadListDataFromFirebase() } частная функция loadListDataFromFirebase () { охранник пусть listName = listName else { print("Ошибка: имя списка равно нулю") возвращаться } listRef = data.child(listName) listRef?.observe(.value, with: {снимок в вар newItems: [ListTextField] = [] для ребенка в snapshot.children { если let childSnapshot = child as? Снимок данных, пусть listItem = ListTextField (снимок: childSnapshot) { newItems.append(listItem) } еще { print("Ошибка преобразования снимка ListTextField") } } self.items = новые элементы DispatchQueue.main.async { self.newListTableView.reloadData() } }) } переопределить func viewWillDisappear(_animated: Bool) { super.viewWillDisappear(анимированный) listRef?.removeAllObservers() } переопределить функцию viewDidLayoutSubviews() { супер.viewDidLayoutSubviews() gradientLayer.frame = view.bounds } @IBAction func saveListAction(_ отправитель: Любой) { Guard let listName = listName, !listName.trimmingCharacters(in: .whitespaces).isEmpty else { PresentErrorAlert (сообщение: NSLocalizedString("EMPTY_FIELD_MESSAGE", комментарий: "")) возвращаться } PresentSaveAlert (имя списка: имя списка) } func saveDataInFirebase (listName: String) { Guard let uid = Auth.auth().currentUser?.uid else { print("Ни один пользователь не вошел в систему.") возвращаться } // Aquí es donde estamos eliminando los espacios en blanco al principio y al Final de listName пусть listNameTrimmed = listName.trimmingCharacters(in: .whitespacesAndNewlines) let listRef = Database.database().reference().child("userLists").child(uid).child(listNameTrimmed).child("items") var itemsData: [Строка: [Строка: Любой]] = [:] для элемента в элементах { itemsData[item.id] = item.toAnyObject() как? [Строка: любая] } print("ItemsData: \(itemsData)") let dataToSave = ["items": itemsData] print("Данные охраняются: \(dataToSave)") listRef.updateChildValues(dataToSave) { (ошибка, _) в если пусть ошибка = ошибка { print("Не удалось сохранить данные в Firebase: \(ошибка)") } еще { print("Данные успешно сохранены в Firebase.") } } } @IBAction func showListAction(_ отправитель: Любой) { пусть раскадровка = UISstoryboard (имя: «Основной», пакет: ноль) если позволить notePadVC = Storyboard.instantiateViewController(withIdentifier: "NotePadView") как? БлокнотПросмотр { notePadVC.listName = self.listName?.capitalized // Осталось имя текущего списка notePadVC.items = self.items // Необходимо оставить элементы также NavigationController?.pushViewController(notePadVC, анимированный: true) } еще { print("Не могу создать экземпляр NotePadView") } } func tableView (_ tableView: UITableView, раздел NumberOfRowsInSection: Int) -> Int { вернуть предметы.счет } func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("Создать элемент NewListView для indexPath: \(indexPath)") Guard let Cell = tableView.dequeueReusableCell (withIdentifier: NewListCell.reuseIdentifier, for: indexPath) как? NewListCell еще { вернуть UITableViewCell() } пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" cell.itemTextField.text = элементы[indexPath.row].title ячейка.indexPath = indexPath cell.onEditAction = { [weak self] newItemTitle, newSubItemTitle, indexPath в охранник пусть StrongSelf = self, пусть indexPath = indexPath еще {возвращение} // Актуализация в Firebase StrongSelf.database.child("\(nombreDeLaLista)/\(strongSelf.items[indexPath.row].id)/title").setValue(newItemTitle) // Актуализация локального списка StrongSelf.items[indexPath.row].title = newItemTitle // Актуализация таблицы tableView.reloadRows(at: [indexPath], с: .automatic) } cell.onDeleteAction = { [weak self] indexPath в охранник пусть StrongSelf = self, пусть indexPath = indexPath еще {возвращение} let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Забрать элемент Firebase StrongSelf.database.child("\(nombreDeLaLista)/\(strongSelf.items[indexPath.row].id)").removeValue() // Выбрать элемент локального списка StrongSelf.items.remove(at: indexPath.row) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: ноль)) StrongSelf.present(предупреждение, анимация: true) } print("Создание NewListView с названием элемента: \(items[indexPath.row].title)") возвратная ячейка } func tableView (_ tableView: UITableView, TrailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> Конфигурация UISwipeActions? { пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" let deleteAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Eliminar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Забрать элемент Firebase self.database.child("\(nombreDeLaLista)/\(self.items[indexPath.row].id)").removeValue() // Выбрать элемент локального списка self.items.remove(в: indexPath.row) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: ноль)) self.present(предупреждение, анимированное: true) завершение (правда) } пусть конфигурация = UISwipeActionsConfiguration (действия: [deleteAction]) возврат конфигурации } func tableView (_ tableView: UITableView, LeadSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" let editAction = UIContextualAction(style: .normal, title: NSLocalizedString("Editar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Editar", комментарий: ""), message: NSLocalizedString("Ingresa el nuevo valor.", комментарий: ""),eferredStyle: .alert) alert.addTextField { (textField) в textField.text = self.items[indexPath.row].title } alert.addAction(UIAlertAction(title: NSLocalizedString("Actualizar", комментарий: ""), стиль: .default, обработчик: { _ in если let textField = alert.textFields?.во-первых, пусть text = textField.text { // Актуализация в Firebase self.database.child("\(nombreDeLaLista)/\(self.items[indexPath.row].id)/title").setValue(text) // Актуализация локального списка self.items[indexPath.row].title = текст // Актуализация таблицы tableView.reloadRows(at: [indexPath], с: .automatic) } })) alert.addAction(UIAlertAction(title: NSLocalizedString("Cancelar", комментарий: ""), стиль: .cancel, обработчик: ноль)) self.present(предупреждение, анимированное: true) завершение (правда) } editAction.backgroundColor = .blue пусть конфигурация = UISwipeActionsConfiguration (действия: [editAction]) возврат конфигурации } } struct ListTextField: Декодируемый { идентификатор переменной: строка переменное название: String вар подзаголовок: Строка вар isChecked: Bool init(id: String, title: String, подзаголовок: String, isChecked: Bool) { self.id = идентификатор self.title = заголовок self.subtitle = субтитр self.isChecked = isChecked } init?(снимок: DataSnapshot) { охранник пусть значение = snapshot.value как? [Строка: ЛюбойОбъект], пусть id = значение["id"] как? Нить, let title = value["title"] как? Нить, let subtitle = value["subtitle"] как? Нить, пусть isChecked = значение ["isChecked"] как? Логическое еще { вернуть ноль } self.id = идентификатор self.title = заголовок self.subtitle = субтитр self.isChecked = isChecked } func toAnyObject() -> Любой { возвращаться [ "я сделал, «титул»: заголовок, «субтитр»: субтитр, «isChecked»: isChecked ] } }
Я столкнулся с проблемой в своем приложении, которую не могу решить. В моем проекте есть разные представления, в которых пользователь может выбрать еду для списка покупок. Когда пользователь выбрал по категориям все элементы для добавления в список, они сохраняются и отображаются в firstView, где расположены все списки, сохраненные пользователями. Моя проблема в том, что я пытаюсь увидеть в списке только те элементы, которые были загружены, и теперь я сталкиваюсь с этой проблемой как с циклом, потому что, когда я нажимаю на ячейки, эти элементы смешиваются и отображаются в разных списках, где они были. не загружен. Я пытался добавить переменную с уникальным идентификатором для элемента или списка, чтобы избежать этого, но это было невозможно, я ошибся в чем-то другом. Могу ли я получить некоторую помощь, пожалуйста?
импортировать UIKit импортировать Firebase импортировать FirebaseAuth импортировать базу данных FirebaseDatabase импортировать локальную аутентификацию класс FirstView: UIViewController, UITableViewDelegate, UITableViewDataSource { func DidSaveNewList (listName: String, items: [ListTextField]) { охранник !listName.isEmpty еще { print("Номер списка не может быть удален.") print("Сохраняем новый список с номером: \(listName) и элементами: \(items)") возвращаться } пусть listData: [Строка: Любой] = [ "имя_списка": имя_списка, "предметы": items.map { $0.toAnyObject() } ] let userRef = Database.database().reference(withPath: "userLists/\(Auth.auth().currentUser!.uid)/\(listName)") userRef.setValue(listData) {ошибка, _ в если пусть ошибка = ошибка { print("Не удалось сохранить данные: \(ошибка).") } еще { print("Данные успешно сохранены!") self.lists[listName] = элементы self.firstTableView.reloadData() } } } списки переменных: [String: [ListTextField]] = [:] var listName: String? элементы var: [ListTextField]? переопределить func viewWillAppear(_animated: Bool) { super.viewWillAppear(анимированный) если пусть пользователь = Auth.auth().currentUser { loadListsFromFirebase (uid: user.uid) } } переопределить функцию viewDidLoad() { супер.viewDidLoad() настройкаUI() } деинит { NotificationCenter.default.removeObserver(self) } func newListSaved(listName: String, items: [Product]) { let ConvertItems = items.map {продукт в ListTextField(id: product.id, заголовок: product.name_es, подзаголовок: товар.категория, isChecked: product.isChecked) } print("Новый список охраняемых номеров: \(listName) и продуктов: \(items)") print("Преобразованные элементы: \(convertedItems)") списки[listName] = конвертированные элементы firstTableView.reloadData() } частная функция loadListsFromFirebase (uid: String) { print("Начало загрузкиListsFromFirebase для пользователя \(uid)") let ref = Database.database().reference().child("userLists").child(uid) ref.observe(.value) { [слабый собственный] снимок в print("Наблюдение за событиями в Firebase") var newLists: [String: [ListTextField]] = [:] для ребенка в snapshot.children { если let childSnapshot = child as? DataSnapshot, пусть значение = childSnapshot.value как? [Строка: любая] { пусть listName = childSnapshot.key print("Обработка списка с номером: \(listName)") если let itemsData = value["items"] как? [[Строка: Любая]] { элементы var: [ListTextField] = [] для itemData в itemsData { если пусть id = itemData["id"] как? Нить, let title = (itemData["name_es"] as? String) ?? (itemData["title"] как? Строка), let subtitle = (itemData["category"] as? String) ?? (itemData["subtitle"] как? Строка), пусть isChecked = itemData["isChecked"] как? Бул { пусть listItem = ListTextField (id: id, title: title, subtitle: subtitle, isChecked: isChecked) items.append(listItem) print("Элемент, объединенный в список \(listName): \(listItem)") } } newLists[listName] = элементы } Еще, если let itemsData = value["items"] as? [Строка: [Строка: Любой]], letnestedItems = itemsData["items"] { элементы var: [ListTextField] = [] for (id, itemData) вnestedItems { если пусть itemData = itemData как? [Строка: любая], let title = itemData["title"] как? Нить, let subtitle = itemData["subtitle"] как? Нить, пусть isChecked = itemData["isChecked"] как? Бул { пусть listItem = ListTextField (id: id, title: title, subtitle: subtitle, isChecked: isChecked) items.append(listItem) print("Объединенный элемент в список \(listName): \(Элемент списка)") } } newLists[listName] = элементы } } } self?.lists = новые списки DispatchQueue.main.async { print("Вернуть данные таблицы") сам?.firstTableView.reloadData() } } } // Расширение класса: func tableView (_ tableView: UITableView, раздел NumberOfRowsInSection: Int) -> Int { print("Обновлен номер файла в разделе: \(section), count: \(lists.count)") вернуть lists.keys.count } func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("Откройте папку indexPath: \(indexPath), listas: \(lists)") Guard let Cell = tableView.dequeueReusableCell (withIdentifier: FirstCell.firstIdentifier, for: indexPath) как? FirstCell еще { FatalError("Ячейка, исключенная из очереди, не является экземпляром FirstCell.") } пусть listName = Array(lists.keys).sorted()[indexPath.row] cell.mainLabel.text = имя_списка.заглавными буквами cell.layer.cornerRadius = 10 cell.clipsToBounds = правда print("Создание списка с именем: \(listName)") возвратная ячейка } func tableView (_ tableView: UITableView, TrailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> Конфигурация UISwipeActions? { let deleteAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Eliminar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Выбрать элемент локального списка пусть listKey = Array(self.lists.keys)[indexPath.row] self.lists.removeValue(forKey: listKey) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) завершение (правда) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: { _ in завершение (ложь) })) self.present(предупреждение, анимированное: true) } вернуть UISwipeActionsConfiguration (действия: [deleteAction]) } func tableView (_ tableView: UITableView, DidSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, анимированный: true) пусть selectedListName = Array(lists.keys)[indexPath.row] пусть selectedListItems = списки[selectedListName] пусть раскадровка = UISstoryboard (имя: «Основной», пакет: ноль) если позволить newListView = Storyboard.instantiateViewController(withIdentifier: "NewListView") как? НьюЛистВью { newListView.listName = выбранноеИмяСписка newListView.items = selectedListItems ?? [] NavigationController?.pushViewController(newListView, анимированный: true) } еще { print("Невозможно создать NewListView") } } } Второе представление для отображения элементов в списке:
импортировать UIKit импортировать Firebase импортировать FirebaseAuth импортировать базу данных FirebaseDatabase класс NewListView: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet слабая вар addItemTextFieldNew: UITextField! @IBOutlet слабая переменная showListButton: UIButton! @IBOutlet слабая переменная saveListButton: UIButton! @IBOutlet слабая переменная plusButtonAdd: UIButton! @IBOutlet слабая вар newListTableView: UITableView! частный пусть градиентный слой = CAGradientLayer() частная база данных let = Database.database().reference(withPath: "iFoodList") частный список переменныхRef: DatabaseReference? var listName: String? элементы var: [ListTextField] = [] списки переменных: [String: [ListTextField]] = [:] переопределить функцию viewDidLoad() { супер.viewDidLoad() охранник пусть tableView = newListTableView еще {возвращение} tableView.delegate = сам tableView.dataSource = сам tableView.register(UINib(nibName: "NewListCell", пакет: ноль), forCellReuseIdentifier: NewListCell.reuseIdentifier) tableView.estimatedRowHeight = 66 tableView.rowHeight = UITableView.automaticDimension self.title = имя_списка ?? «Новый список» view.backgroundColor = .white настроитьUI() loadListDataFromFirebase() } частная функция loadListDataFromFirebase () { охранник пусть listName = listName else { print("Ошибка: имя списка равно нулю") возвращаться } listRef = data.child(listName) listRef?.observe(.value, with: {снимок в вар newItems: [ListTextField] = [] для ребенка в snapshot.children { если let childSnapshot = child as? Снимок данных, пусть listItem = ListTextField (снимок: childSnapshot) { newItems.append(listItem) } еще { print("Ошибка преобразования снимка ListTextField") } } self.items = новые элементы DispatchQueue.main.async { self.newListTableView.reloadData() } }) } переопределить func viewWillDisappear(_animated: Bool) { super.viewWillDisappear(анимированный) listRef?.removeAllObservers() } переопределить функцию viewDidLayoutSubviews() { супер.viewDidLayoutSubviews() gradientLayer.frame = view.bounds } @IBAction func saveListAction(_ отправитель: Любой) { Guard let listName = listName, !listName.trimmingCharacters(in: .whitespaces).isEmpty else { PresentErrorAlert (сообщение: NSLocalizedString("EMPTY_FIELD_MESSAGE", комментарий: "")) возвращаться } PresentSaveAlert (имя списка: имя списка) } func saveDataInFirebase (listName: String) { Guard let uid = Auth.auth().currentUser?.uid else { print("Ни один пользователь не вошел в систему.") возвращаться } // Aquí es donde estamos eliminando los espacios en blanco al principio y al Final de listName пусть listNameTrimmed = listName.trimmingCharacters(in: .whitespacesAndNewlines) let listRef = Database.database().reference().child("userLists").child(uid).child(listNameTrimmed).child("items") var itemsData: [Строка: [Строка: Любой]] = [:] для элемента в элементах { itemsData[item.id] = item.toAnyObject() как? [Строка: любая] } print("ItemsData: \(itemsData)") let dataToSave = ["items": itemsData] print("Данные охраняются: \(dataToSave)") listRef.updateChildValues(dataToSave) { (ошибка, _) в если пусть ошибка = ошибка { print("Не удалось сохранить данные в Firebase: \(ошибка)") } еще { print("Данные успешно сохранены в Firebase.") } } } @IBAction func showListAction(_ отправитель: Любой) { пусть раскадровка = UISstoryboard (имя: «Основной», пакет: ноль) если позволить notePadVC = Storyboard.instantiateViewController(withIdentifier: "NotePadView") как? БлокнотПросмотр { notePadVC.listName = self.listName?.capitalized // Осталось имя текущего списка notePadVC.items = self.items // Необходимо оставить элементы также NavigationController?.pushViewController(notePadVC, анимированный: true) } еще { print("Не могу создать экземпляр NotePadView") } } func tableView (_ tableView: UITableView, раздел NumberOfRowsInSection: Int) -> Int { вернуть предметы.счет } func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { print("Создать элемент NewListView для indexPath: \(indexPath)") Guard let Cell = tableView.dequeueReusableCell (withIdentifier: NewListCell.reuseIdentifier, for: indexPath) как? NewListCell еще { вернуть UITableViewCell() } пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" cell.itemTextField.text = элементы[indexPath.row].title ячейка.indexPath = indexPath cell.onEditAction = { [weak self] newItemTitle, newSubItemTitle, indexPath в охранник пусть StrongSelf = self, пусть indexPath = indexPath еще {возвращение} // Актуализация в Firebase StrongSelf.database.child("\(nombreDeLaLista)/\(strongSelf.items[indexPath.row].id)/title").setValue(newItemTitle) // Актуализация локального списка StrongSelf.items[indexPath.row].title = newItemTitle // Актуализация таблицы tableView.reloadRows(at: [indexPath], с: .automatic) } cell.onDeleteAction = { [weak self] indexPath в охранник пусть StrongSelf = self, пусть indexPath = indexPath еще {возвращение} let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Забрать элемент Firebase StrongSelf.database.child("\(nombreDeLaLista)/\(strongSelf.items[indexPath.row].id)").removeValue() // Выбрать элемент локального списка StrongSelf.items.remove(at: indexPath.row) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: ноль)) StrongSelf.present(предупреждение, анимация: true) } print("Создание NewListView с названием элемента: \(items[indexPath.row].title)") возвратная ячейка } func tableView (_ tableView: UITableView, TrailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> Конфигурация UISwipeActions? { пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" let deleteAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Eliminar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Eliminar", комментарий: ""), message: NSLocalizedString("¿Estás seguro de que quieres eliminar este element?", comment: ""),eferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("Sí", комментарий: ""), стиль: .destructive, обработчик: { _ in // Забрать элемент Firebase self.database.child("\(nombreDeLaLista)/\(self.items[indexPath.row].id)").removeValue() // Выбрать элемент локального списка self.items.remove(в: indexPath.row) // Актуализация таблицы tableView.deleteRows(at: [indexPath], с: .automatic) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Нет", комментарий: ""), стиль: .cancel, обработчик: ноль)) self.present(предупреждение, анимированное: true) завершение (правда) } пусть конфигурация = UISwipeActionsConfiguration (действия: [deleteAction]) возврат конфигурации } func tableView (_ tableView: UITableView, LeadSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { пусть nombreDeLaLista = listName ?? "имя_списка по умолчанию" let editAction = UIContextualAction(style: .normal, title: NSLocalizedString("Editar", комментарий: "")) { (действие, просмотр, завершение) в let alert = UIAlertController(title: NSLocalizedString("Editar", комментарий: ""), message: NSLocalizedString("Ingresa el nuevo valor.", комментарий: ""),eferredStyle: .alert) alert.addTextField { (textField) в textField.text = self.items[indexPath.row].title } alert.addAction(UIAlertAction(title: NSLocalizedString("Actualizar", комментарий: ""), стиль: .default, обработчик: { _ in если let textField = alert.textFields?.во-первых, пусть text = textField.text { // Актуализация в Firebase self.database.child("\(nombreDeLaLista)/\(self.items[indexPath.row].id)/title").setValue(text) // Актуализация локального списка self.items[indexPath.row].title = текст // Актуализация таблицы tableView.reloadRows(at: [indexPath], с: .automatic) } })) alert.addAction(UIAlertAction(title: NSLocalizedString("Cancelar", комментарий: ""), стиль: .cancel, обработчик: ноль)) self.present(предупреждение, анимированное: true) завершение (правда) } editAction.backgroundColor = .blue пусть конфигурация = UISwipeActionsConfiguration (действия: [editAction]) возврат конфигурации } } struct ListTextField: Декодируемый { идентификатор переменной: строка переменное название: String вар подзаголовок: Строка вар isChecked: Bool init(id: String, title: String, подзаголовок: String, isChecked: Bool) { self.id = идентификатор self.title = заголовок self.subtitle = субтитр self.isChecked = isChecked } init?(снимок: DataSnapshot) { охранник пусть значение = snapshot.value как? [Строка: ЛюбойОбъект], пусть id = значение["id"] как? Нить, let title = value["title"] как? Нить, let subtitle = value["subtitle"] как? Нить, пусть isChecked = значение ["isChecked"] как? Логическое еще { вернуть ноль } self.id = идентификатор self.title = заголовок self.subtitle = субтитр self.isChecked = isChecked } func toAnyObject() -> Любой { возвращаться [ "я сделал, «титул»: заголовок, «субтитр»: субтитр, «isChecked»: isChecked ] } }
Мобильная версия