简体   繁体   中英

Swift NSFetchedResultsController Sections Always returns nil

I'm very new on swift, and I'm trying to make a App to learn o bit of it. I created a simple App to store some books' information and show it then on a CollectionView .

I have made a simple datamodel and it has an entity of Books (Livro) with some attributes, including category, title and a image (to show on CV). I'd like to show then divided in sections (by Category - categoria).

My problem is that I can Fetch the data from Data-Core, I can list all of then on console, but fetchResultsController.sections always return nil, even when the "categoria" attribute has some value.

The delegate CV method numberOfSections (in collection view) is called but it returns 0, and de CV delegate cellForItemAt is NEVER called.

Here are some of my code on my UIViewController:

    override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    ListaLivros.delegate = self
    ListaLivros.dataSource = self

    if let context = container?.viewContext {
        let sortDescriptor = NSSortDescriptor(key: "titulo", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
        let sortDescriptorSections = NSSortDescriptor(key: "categoria", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))

        let request: NSFetchRequest<Livro> = Livro.fetchRequest()
        request.sortDescriptors = [sortDescriptor, sortDescriptorSections]
        request.predicate = nil

        fetchedResultsController = NSFetchedResultsController<Livro>(
            fetchRequest: request,
            managedObjectContext: context,
            sectionNameKeyPath: "categoria",
            cacheName: nil)
        fetchedResultsController?.delegate = self

        //------______---======   PRINT BOOKS   ------______---======
        if let results = try? context.fetch(Livro.fetchRequest()) {

            for livro in results {
                print ("  -> Secoes: \(String(describing: fetchedResultsController?.sections))")
                print ("   --> Livro: \(livro)")
//                    context.delete(livro as! NSManagedObject)
//                    try? context.save()
            }
        }
        //------______---======   TESTE   ------______---======
    }

    atualizaView()
    mostraBDStats ()
} // DIDLOAD

I put the delegate functions all on extensions. The CoreData portion seems to work ok, since it is inserting the data on DataCore. So, I'm posting only my CV extension:

extension ListaLivrosVC: UICollectionViewDelegate, UICollectionViewDataSource {
    func numberOfSections( in collectionView: UICollectionView) - > Int {
        print("Num Sec: (String(describing: fetchedResultsController?.sections?.count))")

    if let context = container?.viewContext {
        //------______---======   PRINT BOOKS   ------______---======
        if let results = try? context.fetch(Livro.fetchRequest()) {
            for livro in results {
                print ("  -> 2Secoes: \(String(describing: fetchedResultsController))")
                print ("   --> 2Livro: \(livro)")
                //                    context.delete(livro as! NSManagedObject)
                //                    try? context.save()
            }
        }
    }
    return fetchedResultsController?.sections?.count ?? 0
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    guard let sections = fetchedResultsController?.sections else { return 0 }

    if !PickerSecoes.contains(sections[section].name) {
        PickerSecoes.append(sections[section].name)
    }

    return sections[section].numberOfObjects

} // COLLECTION

//--------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let celula = ListaLivros.dequeueReusableCell(withReuseIdentifier: "LivrosCell", for: indexPath)

    if let LivroCelula = celula as? LivroCollectionCell {
        if let livro = fetchedResultsController?.object(at: indexPath) {
            LivroCelula.Imagem.image = livro.getImagem()
            LivroCelula.Titulo.text = livro.titulo
        } // if
    } // IF

    return celula
} // COLLECTION
}

I don't know what else I can do. Running the App, I can see 2 book I inserted but they do not apear on CV:

Numero de Livros no BD: 2
  -> Secoes: nil
   --> Livro: Titulo: Optional("teste"), Autores: Optional("teste123"), Categoria: Optional("testetestes"), Tags: nil
  -> Secoes: nil
   --> Livro: Titulo: Optional("teste2"), Autores: Optional("tests do"), Categoria: Optional("casa"), Tags: nil
Num Sec: nil
  -> 2Secoes: Optional(<NSFetchedResultsController: 0x600003382700>)
   --> 2Livro: Titulo: Optional("teste"), Autores: Optional("teste123"), Categoria: Optional("testetestes"), Tags: nil
  -> 2Secoes: Optional(<NSFetchedResultsController: 0x600003382700>)
   --> 2Livro: Titulo: Optional("teste2"), Autores: Optional("tests do"), Categoria: Optional("casa"), Tags: nil
Numero de Livros no BD: 2

Just to complement, in the same App I have two other similar Entities. Both of them I could successfully list on a TableView with sections. The code above was copied from them and adapted to use the CollectionView.

I'm using XCode 10, Swift 4.2

Answering my own question, I think I realized what's wrong, although I don't know why it is wrong and why it works with another Entity with TableView.

The problem seems to me the predicate. Commenting the line:

    request.predicate = nil

seems to solve the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM