Как настроить collectionView (или TableView) с NSFetchedResultsController и несколькими извлеченными объектами - PullRequest
1 голос
/ 16 января 2020

Я прочитал здесь, что способ извлечения нескольких сущностей с 1 NSFetchedResultsController заключается в использовании родительской модели наследования дочерних элементов. У меня есть такая модель:

https://imgur.com/a/nckHzvr

Как вы видите, TextPost, VideoPost и ImagePost все имеют Skill в качестве родительского объекта. Я пытаюсь сделать один collectionView, для которого появляются все три ребенка. Я немного сбит с толку относительно того, как установить методы делегата, хотя ...

Вот код для контроллера представления

class Timeline2ViewController: UIViewController {

    @IBOutlet var postsCollectionView: UICollectionView!
    var skillName: String?

    fileprivate lazy var skillFetchedResultsController: NSFetchedResultsController<Skill> = {
        let appDelegate =
            UIApplication.shared.delegate as? AppDelegate
        let managedContext =
            appDelegate?.persistentContainer.viewContext
        let request: NSFetchRequest<Skill> = NSFetchRequest(entityName: "Skill")
        request.predicate = NSPredicate(format: "name == %@", self.skillName!)
        let timeSort = NSSortDescriptor(key: "timeStamp", ascending: true)
        request.sortDescriptors = [timeSort]

        let skillFetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: managedContext!, sectionNameKeyPath: nil, cacheName: nil)
        return skillFetchedResultsController
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            try skillFetchedResultsController.performFetch()
        } catch let error as NSError {
            print("SkillFetchError")
        }
    }
}
extension Timeline2ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        guard let sectionInfo = skillFetchedResultsController.sections?[section] else { return 0 }
        return sectionInfo.numberOfObjects
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = postsCollectionView.dequeueReusableCell(withReuseIdentifier: "pcell", for: indexPath) as? PostViewCell else { return fatalError("unexpected Index Path")
        }
        let post = skillFetchedResultsController[indexPath.row] /* This is the line im not sure about
        cell.background
        return cell
    }
}

Поскольку на самом деле возвращается только 1 сущность, я я не уверен, как получить доступ к элементу по указанному c пути индекса. Например, skillFetchedResultsController [indexPath.row], я думаю, имеет только 1 сущность - сам навык. Я действительно хочу получить доступ к своим детям. Должен ли я каким-то образом создавать подкласс skillFetchedResultsController и возвращать только тех детей, которые мне интересны?

Редактировать: с предложениями @pbasdf - у меня есть эта модель:

enter image description here

Теперь, когда я создаю объект, подобный так:

        guard let appDelegate =
         UIApplication.shared.delegate as? AppDelegate else {
             return
         }
         let managedContext = appDelegate.persistentContainer.viewContext
        let textPost = NSEntityDescription.insertNewObject(forEntityName: "TextPost", into: managedContext) as! TextPost
        textPost.text = "test text post"
        try! managedContext.save()

и я настроил свой контроллер полученных результатов так, чтобы он выглядел на «Post2» следующим образом:

    fileprivate lazy var skillFetchedResultsController: NSFetchedResultsController<Post2> = {
        let appDelegate =
            UIApplication.shared.delegate as? AppDelegate
        let managedContext =
            appDelegate?.persistentContainer.viewContext
        let request: NSFetchRequest<Post2> = NSFetchRequest(entityName: "Post2")
//        request.predicate = NSPredicate(format: "skill = %@", self.skill!)
        let timeSort = NSSortDescriptor(key: "timeStamp", ascending: true)
        request.sortDescriptors = [timeSort]
        let skillFetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: managedContext!, sectionNameKeyPath: nil, cacheName: nil)
        return skillFetchedResultsController
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        do {
            try skillFetchedResultsController.performFetch()
        } catch _ as NSError {
            print("SkillFetchError")
        }

    }

Я не вижу возвращаемых результатов в:

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

Должен ли я как-то нужно связать два? Как создать объект Post и объект TextPost одновременно? Когда я пытаюсь получить объекты TextPost напрямую, это работает.

1 Ответ

1 голос
/ 16 января 2020

Я думаю, что проблема заключается в вашей модели. Вам следует создать сущность Post и сделать ее родительской сущностью TextPost, VideoPost и ImagePost. Если у ваших подразделений есть какие-либо общие атрибуты, переместите их из подразделов в Post. Затем установите sh отношение «один-много» от Skill до Post.

Ваш FR C должен получить Post объектов (которые по умолчанию будут включать все субтитры), используя предикат при необходимости ограничить его теми Post объектами, которые относятся к желаемому Skill объекту, например

NSPredicate(format:"skill.name == %@",self.skillName!)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...