Обновление данных в TableView СРАЗУ после добавление элемента

swift

#1

Доброго времени суток! Несколько дней назад начал изучение Swift по книге “Swift для детей”. Короче говоря, с нуля. В качестве примера в ней разбирается процесс создания простейшего приложения, позволяющего добавлять дни рождения друзей и получать уведомления. Казалось бы, что может пойти не так, когда требовалось всего-лишь списать код из книги. Но я столкнулся со следующей проблемой: СРАЗУ же после добавления новых данных (информации о дне рождения) НЕ происходит обновление таблицы. Форма для ввода данных исчезает и перед глазами пользователя всё та же пустая таблица. Она, конечно, обновляется, но только ПОСЛЕ ПЕРЕЗАПУСКА (выключил - включил) приложения. Хотелось бы узнать, каким образом это можно исправить?

Хочу сразу предупредить: функция ReloadData () ПРИСУТСТВУЕТ. И да, она именно в методе viewWillAppear. Ниже привожу код. Прошу, подскажите решение.

Таблица:

    class BirthdaysTableViewController: UITableViewController {

        var birthdays = [Birthday] ()
        let dateFormatter = DateFormatter ()
        override func viewDidLoad() {
            super.viewDidLoad()
            dateFormatter.dateStyle = .full
            dateFormatter.timeStyle = .none
        }
        
        override func viewWillAppear (_ animated: Bool) {
            super.viewWillAppear (true)
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let context = appDelegate.persistentContainer.viewContext
            let fetchRequest = Birthday.fetchRequest() as NSFetchRequest<Birthday>
            let sortDescriptor1 = NSSortDescriptor (key: "lastName", ascending: true)
            let sortDescriptor2 = NSSortDescriptor (key: "firstName", ascending: true)
            fetchRequest.sortDescriptors = [sortDescriptor1, sortDescriptor2]
            do {
                birthdays = try context.fetch (fetchRequest)
            } catch let error {
                print ("There is error: \(error)")
            }
            tableView.reloadData()
        }

        // MARK: - Table view data source

        override func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }

        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return birthdays.count
        }


        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "birthdayCellIdentifier", for: indexPath)
            let birthday = birthdays[indexPath.row]
            let firstName = birthday.firstName ?? ""
            let lastName = birthday.lastName ?? ""
            cell.textLabel?.text = firstName + " " + lastName
            
            if let date = birthday.birthdate as Date? {
                cell.detailTextLabel?.text = dateFormatter.string(from: date)
            } else {
                cell.detailTextLabel?.text = " "
            }
            return cell
        }
        override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
            return true
        }
        
        override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
            if birthdays.count > indexPath.row {
                let birthday = birthdays [indexPath.row]
                if let identifier = birthday.birthdayId {
                    let center = UNUserNotificationCenter.current()
                    center.removePendingNotificationRequests(withIdentifiers:
                       [identifier])
                }
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                let context = appDelegate.persistentContainer.viewContext
                context.delete(birthday)
                birthdays.remove(at: indexPath.row)
                do {
                    try context.save ()
                } catch let error {
                    print ("There is an error \(error)")
                }
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
        }
    }

Форма для добавления данных:

class AddBirthdayViewController: UIViewController {

    @IBOutlet var firstNameTextField: UITextField!
    @IBOutlet var lastNameTextField: UITextField!
    @IBOutlet var birthdatePicker: UIDatePicker!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        birthdatePicker.maximumDate = Date()
    }
    @IBAction func saveTapped (_ sender: UIBarButtonItem) {
        let firstName = firstNameTextField.text ?? ""
        let lastName = lastNameTextField.text ?? ""
        let birthdate = birthdatePicker.date
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let context = appDelegate.persistentContainer.viewContext
        let newBirthday = Birthday (context: context)
        newBirthday.firstName = firstName
        newBirthday.lastName = lastName
        newBirthday.birthdate = birthdate as Date?
        newBirthday.birthdayId = UUID () .uuidString
        do {
            try context.save ()
            let message = "Сегодня \(firstName) \(lastName) празднует 8 день рождения!"
            let content = UNMutableNotificationContent()
            content.body = message
            content.sound = UNNotificationSound.default
            var dateComponents = Calendar.current.dateComponents([.month, .day], from: birthdate)
            dateComponents.hour = 19
            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
            if let identifier = newBirthday.birthdayId {
            let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
            let center = UNUserNotificationCenter.current()
                center.add(request, withCompletionHandler: nil)
            }
        } catch let error {
            print ("There is an error \(error)")
        }
        dismiss(animated: true, completion: nil)
    }
    @IBAction func cancelTapped (_ sender: UIBarButtonItem) {
        dismiss(animated: true, completion: nil)
    }
}

#2

Очевидно, что таблицу надо обновлять сразу после добавления новых данных в методе saveTapped


#3

Укажите, пожалуйста, на конкретные изменения в коде. Грубо говоря, скажите ЧТО и КУДА писать. Самому мне не разобраться. Если, конечно, Вам не сложно


#4

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


#5

Попробуйте перенести в viewDidAppear.


#6

Тебе нужно обновить таблицу, используй твояТаблица.reloadData().
Помести это во viewwillappear() и каждый раз, когда вьюха будет появляться, таблица будет обновляться.
Либо да, reloadData() перед dismiss в saveTapped.


#7

Ну что, помогли Вам ответы?


#8

Он никак не сможет вызвать ReloadData в save tapped, так как RData это метод из UIViewTableController, а savetapped в UIViewController


#9

как уже здесь было сказано, обновление таблицы надо вызывать во viewDidAppear, потому что viewWillAppear срабатывает раньше, чем приходят данные. Поэтому они становятся видны в таблице только при следующем перезапуске.