2017-12-13 5 views
0

Im Erhalten von Benutzereingaben und Erstellen von CoreData-Entität dafür, und in die TableView einfügen, aber bevor ich einige Eigenschaften für die Entität durch ein paar Netzwerkanforderungen festlegen müssen. Und es gibt ein Problem. Die erste Entity ist immer null (und eine leere Zelle für die Tabellenansicht erstellen), aber wenn ich den Kontext speichere und die App wieder öffne - hier ist es, Entity ist in Ordnung. Wenn ich eine zweite (und so weiter) Entität erstelle, funktioniert es gut. Es scheint auch wie Tisch immer leere Zelle für den Start zu erstellen und dann löschen Sie es und erstellen Sie die richtige Zelle ... Ich kann nicht bekommen, warum Abschlusshandler nicht ordnungsgemäß funktioniert und Netzwerkanforderungen asynchron macht. Bitte hilf mir zu verstehen.Swift synchronisieren Netzwerkanforderung

Creation metod beginnt in textFieldShouldReturn

import UIKit 
import CoreData 

class ViewController: UIViewController, UITextFieldDelegate { 

    var managedObjectContext: NSManagedObjectContext? 
    lazy var fetchedResultsController: NSFetchedResultsController<Word> = { 

     let fetchRequest: NSFetchRequest<Word> = Word.fetchRequest() 
     let createdSort = NSSortDescriptor(key: "created", ascending: false) 
     let idSort = NSSortDescriptor(key: "id", ascending: false) 

     fetchRequest.sortDescriptors = [createdSort, idSort] 

     var fetchedResultsController = NSFetchedResultsController(
      fetchRequest: fetchRequest, 
      managedObjectContext: AppDelegate.viewContext, 
      sectionNameKeyPath: nil, 
      cacheName: nil) 

     fetchedResultsController.delegate = self 

     return fetchedResultsController 
    }() 

    private var hasWords: Bool { 
     guard let fetchedObjects = fetchedResultsController.fetchedObjects else { return false } 
     return fetchedObjects.count > 0 
    } 

    let creator = WordManager.shared 

    @IBOutlet weak var tableView: UITableView! 
    @IBOutlet weak var messageLabel: UILabel! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     managedObjectContext = AppDelegate.viewContext 
     fetchWords() 

     updateView() 
    } 

    func updateView() { 
     tableView.isHidden = !hasWords 
     messageLabel.isHidden = hasWords 
    } 
    ............ 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
     guard let managedObjectContext = managedObjectContext else { return false } 
     guard let title = textField.text, !title.isEmpty, !title.hasPrefix(" ") else { 
      showAllert(title: "Warning!", message: "Title may not to be nil!") 
      return false 
     } 

     let word = Word(context: managedObjectContext) 
     guard let fetchedWordsCount = fetchedResultsController.fetchedObjects?.count else { return false } 

     creator.createWord(title: title, counter: fetchedWordsCount, word: word) 
     self.updateView() 

     textField.text = nil 

     return true 
    } 


    func fetchWords() { 
     do { 
      try fetchedResultsController.performFetch() 
     } catch { 
      fatalError("Cant fetch words. Error \(error.localizedDescription)") 
     } 
    } 
} 

Einheit Erstellen

import CoreData 
import UIKit 

class WordManager { 
    static var shared = WordManager() 
    private init() {} 

    private var api = DictionaryAPI() 
    private var api2 = MeaningAPI() 

    func createWord(title: String, counter: Int, word: Word) { 

     self.api.fetch(word: title, completion: { translation in 
      self.api2.fetchTranscription(word: title, completion: { transcription in 

       word.id = Int16(counter) + 1 
       word.title = title 
       word.translation = translation 
       word.transcription = "[\(transcription)]" 
       word.created = NSDate() 
      }) 
     }) 
    } 
} 

Nichts interessant in Tableview

extension ViewController: UITableViewDataSource { 

func numberOfSections(in tableView: UITableView) -> Int { 
    guard let sections = fetchedResultsController.sections else { return 0 } 
    return sections.count 
} 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    guard let section = fetchedResultsController.sections?[section] else { return 0 } 
    return section.numberOfObjects 
} 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "mainCell", for: indexPath) as! MainCell 

    let word = fetchedResultsController.object(at: indexPath) 
    cell.configure(with: word) 

    return cell 
} 

}

konfigurieren c ell Methode

func configure(with word: Word) { 

     titleField.text = word.title 
     translationField.text = word.translation 
     transcriptionLabel.text = word.transcription 
     totalCounter.text = "\(word.showCounter)" 
     correctCounter.text = "\(word.correctCounter)" 
     wrongCounter.text = "\(word.wrongCounter)" 
} 

Fetched Ergebnisse Delegierter

extension ViewController: NSFetchedResultsControllerDelegate { 

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
    tableView.beginUpdates() 
} 

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
    tableView.endUpdates() 
    updateView() 
} 

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 

    switch type { 
    case .delete: 
     guard let indexPath = indexPath else { return } 
     tableView.deleteRows(at: [indexPath], with: .fade) 
    case .insert: 
     guard let indexPath = newIndexPath else { return } 
     tableView.insertRows(at: [indexPath], with: .fade) 
    case .move: 
     guard let indexPath = indexPath else { return } 
     tableView.deleteRows(at: [indexPath], with: .fade) 
     guard let newIndexPath = newIndexPath else { return } 
     tableView.insertRows(at: [newIndexPath], with: .fade) 
    default: 
     break 
    } 
} 

}

enter image description here

Antwort

0

Problem:

  • Die Daten, die Sie in Kerndaten haben, ist nicht in einem Zustand, ist bereit t o in der App angezeigt werden.
  • Die NSFetchedResultsController zufällig passiert, um diese Daten auszuwählen und zeigt es in der App.

Ansatz:

  • Wenn ein Benutzer eine Datensätze erstellt, der Benutzer möchte die Änderungen sofort in der App sehen und sollte nicht warten, bis die App auf dem Server zu aktualisieren, die zu sehen Änderungen. Ein Benutzer kann also auch dann Datensätze erstellen, wenn keine Netzwerkverbindung besteht.
  • Erstellen eines untergeordneten Kontexts aus dem Ansichtskontext
  • Verwenden Sie einen Hintergrundthread zum Hochladen auf den Server und beim Aktualisieren auf den untergeordneten Kontext.
  • Speichern Sie den untergeordneten Kontext nur, wenn sich die Daten in einem konsistenten Zustand befinden.
  • NSFetchedResultsController sollte den View-Kontext verwenden, so dass die Kind Kontext Datensätze nicht bewusst sein.
  • Wenn Sie den untergeordneten Kontext speichern, würde NSFetchedResultsController diese Datensätze auswählen.
+0

Die Sache ist, ich brauche keine schlechten Aufzeichnungen in CoreData. – drywet

+0

Siehe aktualisierte Antwort – user1046037

Verwandte Themen