2016-10-20 3 views
-1

Я пытаюсь вернуть NSFetchRequest с определенными значениями. Это то, что у меня есть:Получите уникальные результаты от NSFetchRequest

class Tag: NSManagedObject { 
    static let entityName = "\(Tag.self)" 

    static var allTagsRequest: NSFetchRequest<NSFetchRequestResult> = { 
     let request = NSFetchRequest<NSFetchRequestResult>(entityName: Tag.entityName) 
     request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] 
     return request 
    }() 

    static var uniqueTagsRequest: NSFetchRequest<NSFetchRequestResult> = { 
     let request = NSFetchRequest<NSFetchRequestResult>(entityName: Tag.entityName) 
     request.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)] 
     request.resultType = .dictionaryResultType 
     request.returnsDistinctResults = true 
     return request 
    }() 
} 

В allTagsRequest возвращается правильно, то он возвращает все теги хранятся в CoreData - даже дублей. Я хочу, чтобы uniqueTagsRequest возвращал только уникальные теги, но когда я это делаю, tableView не заполняется. Вот мой Tableview код:

class SortableDataSource<SortType: CustomTitleConvertible>: NSObject, UITableViewDataSource where SortType: NSManagedObject { 

    let kReuseIdentifier = "sortableItemCell" 

    fileprivate let fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult> 

    var results: [SortType] { 
     return fetchedResultsController.fetchedObjects as! [SortType] 
    } 

    init(fetchRequest: NSFetchRequest<NSFetchRequestResult>, managedObjectContext moc: NSManagedObjectContext) { 
     self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil) 

     super.init() 
     executeFetch() 
    } 

    func executeFetch() { 
     do { 
      try fetchedResultsController.performFetch() 
     } catch let error as NSError { 
      let alertController = UIAlertController(
       title: "Error", 
       message: "\(error.debugDescription)", 
       preferredStyle: .alert) 
      let okAction = UIAlertAction(
       title: "Ok", 
       style: .cancel, 
       handler: nil) 
      alertController.addAction(okAction) 
      UIApplication.topViewController()?.present(alertController, animated: true, completion: nil) 
     } 
    } 

    //MARK: - UITableViewDataSource 
    func numberOfSections(in tableView: UITableView) -> Int { return 2 } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     switch section { 
     case 0: return 1 
     case 1: return fetchedResultsController.fetchedObjects?.count ?? 0 
     default: return 0 
     } 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = UITableViewCell(style: .default, reuseIdentifier: kReuseIdentifier) 
     cell.selectionStyle = .none 

     switch (indexPath.section, indexPath.row) { 
     case (0, 0): 
      cell.textLabel?.text = "All \(SortType.self)s" 
      cell.accessoryType = .checkmark 
     case (1, _): 
      guard let sortItem = fetchedResultsController.fetchedObjects?[indexPath.row] as? SortType else { break} 
      cell.textLabel?.text = sortItem.title 
     default: break 
     } 
     return cell 
    } 
} 

И сортировать контроллер:

@objc fileprivate func presentSortController() { 
     let tagDataSource = SortableDataSource<Tag>(fetchRequest: Tag.uniqueTagsRequest, managedObjectContext: CoreDataController.sharedInstance.managedObjectContext) 
     let sortItemSelector = SortItemSelector(sortItems: tagDataSource.results) 
     let sortController = PhotoSortListController(dataSource: tagDataSource, sortItemSelector: sortItemSelector) 

     sortController.onSortSelection = { checkedItems in 
      if !checkedItems.isEmpty { 
       var predicates = [NSPredicate]() 
       for tag in checkedItems { 
        let predicate = NSPredicate(format: "%K CONTAINS %@", "tags.title", tag.title) 
        predicates.append(predicate) 
       } 
       let compoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates) 
       self.dataSource.performFetch(withPredicte: compoundPredicate) 
      } else { 
       self.dataSource.performFetch(withPredicte: nil) 
      } 
     } 

     let navController = UINavigationController(rootViewController: sortController) 

     present(navController, animated: true, completion: nil) 
    } 

Спасибо, ребята!

ответ

1

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

Таким образом, когда вам нужен уникальный список, вы можете просто сделать небольшой трюк, в котором вы преобразуете массив в NSSet, а затем обратно в массив (это удаляет дубликаты). Когда вы снова получите весь список, вы можете просто восстановить его из оригинала и перезагрузить tableview.

+0

После некоторого кастинга он работал как шарм - спасибо! –

0

Просто мысли вслух, но если вы установите ResultType в

request.resultType = .dictionaryResultType 

будет это действительно работает?

let tagDataSource = SortableDataSource<Tag>(fetchRequest: Tag.uniqueTagsRequest,...) 

var results: [SortType] { 
    return fetchedResultsController.fetchedObjects as! [SortType] 
} 

Won't в fetchedObjects быть [String:Any]?

+0

Вы правы - и это часть моей проблемы. Если я не сделаю resultType .dictionaryResultType, то returnDistinctResults не будет работать. Если я использую .dictionaryResultType, то я не могу заполнить таблицу. –

+0

Я думаю, мне интересно, как вернуть отличные результаты без словаряResultType –

Смежные вопросы