Невозможно правильно создать управляемый объект и сохранить его в основных данных - PullRequest
0 голосов
/ 09 января 2019

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

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

Я создал две сущности (Коллекция и Колода) в основных данных. Каждый с одним атрибутом (title: String). Коллекция имеет отношение «ко многим», а Deck и Decks - «to-one». У меня есть два контроллера таблицы просмотра, каждый с контроллером извлеченных результатов. На панели навигации есть кнопка добавления для каждого контроллера представления, которая позволяет пользователю добавлять коллекцию или колоду (соответственно). Я могу выполнить коллекцию добавления и заставить методы делегата fetchedResultsController запускать и отображать добавленный элемент просто отлично. При выборе элемента строки для коллекций я обращаюсь ко второму контроллеру табличного представления для отображения колод для выбранной коллекции.

У fetchedResultsController во втором TableViewController есть предикат, который проверяет соответствие коллекций колод таким же, как и выбранная коллекция. Я хочу, чтобы отображались только те колоды, которые являются частью выбранной коллекции.

Эта часть работает нормально, но когда пользователь выбирает добавить колоду, он добавляется, но не запускает методы NSFetchedResultsControllerDelegate для отображения колоды в виде таблицы. Если я вернусь к представлению коллекций, затем снова выберу ту же коллекцию, колода появится. Так что я знаю, что это было добавлено.

Проблема состоит из двух частей: 1) Почему NSfetchedResultsControllerDelegate не запускается 2) Я хочу, чтобы пользователь вводил имена Коллекции и Колоды при добавлении через UIAlertController с текстовым полем. Я настроил это, и это работает для CollectionViewController, но я не могу заставить его работать в DecksViewController. Я действительно не знаю, в каком потоке мне следует запускать код или если обработчик AlertAction находится в фоновом потоке.

За последние два дня я просмотрел этот форум и форум Apple на предмет любой помощи.

Вещи, которые я пробовал. Диспетчер главной очереди, передавая управляемый objectID, получая управляемый объектный текст из переданного объекта коллекции, удаляя предикат все вместе, чтобы посмотреть, смогу ли я заставить его работать. Ничто не дает ожидаемого результата.

var collection: CollectionMO!

    private lazy var frc: NSFetchedResultsController<DeckMO> = {
        let fetchRequest:NSFetchRequest<DeckMO> = DeckMO.fetchRequest()
        let sort1 = NSSortDescriptor(key: "title", ascending: true)
        fetchRequest.sortDescriptors = [sort1]
        fetchRequest.predicate = NSPredicate(format: "collection == %@", collection)
        let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: viewContext, sectionNameKeyPath: nil, cacheName: nil)
        frc.delegate = self
        return frc

    }()

    @IBAction func addDeck(_ sender: UIBarButtonItem) {
        nameDeck() // this is the preferred method and remaining code in this action test code to get it working
        let newDeck = DeckMO(context: viewContext)
        newDeck.title = "Deck \((frc.fetchedObjects?.count)! + 1) in \(collection.title ?? "")"
        collection.addToDecks(newDeck)
    }

    private func nameDeck(_ deck:DeckMO? = nil) {

        let alert = UIAlertController.init(title: deck?.title != nil ? "Retitle Deck:" : "Enter New Deck Title",
                                           message: deck?.title ?? "", preferredStyle: .alert)

        alert.addTextField(configurationHandler: { (textField: UITextField) in
            textField.placeholder = deck?.title ?? "Enter Deck Title"
        })

        alert.addAction(UIAlertAction.init(title: "Cancel", style: .destructive, handler: nil))
        alert.addAction(UIAlertAction.init(title: "Save", style: .default, handler: { action in
            if let text1 = alert.textFields?.first, text1.hasText, text1.text != deck?.title {
                if let updateDeck = deck {
                    updateDeck.title = text1.text
                } else {
                    DispatchQueue.main.async {
                        let newDeck = DeckMO(context: self.viewContext)
                        newDeck.title = text1.text
                        newDeck.collection = self.collection
                    }
                }
            }
        }))

        self.present(alert, animated: true)
    }

DeckViewController должен отображать колоду, добавленную сразу после добавления, а DeckViewController должен отображать только колоды выбранной Коллекции из предыдущего viewController.

...