2016-10-20 3 views
-1

Ich versuche, eine NSFetchRequest mit eindeutigen Werten zurückzugeben. Das ist, was ich habe:Erhalten Sie eindeutige Ergebnisse von 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 
    }() 
} 

Die allTagsRequest Rückkehr richtig, das heißt, sie alle Tags kehrt in Coredata gespeichert - auch die Duplikate. Ich möchte, dass die uniqueTagsRequest nur eindeutige Tags zurückgibt, aber wenn ich das tue, füllt das TableView nicht aus. Hier ist meine Tableview-Code:

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 
    } 
} 

und sortieren Controller:

@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) 
    } 

Danke Jungs!

Antwort

1

Wenn ich es wäre, würde ich ein lokales Array mit der allTagsRequest füllen und die NSFetchedResultsController Feed das haben. Dann würde dieses lokale Array die Tabellenansicht füttern.

Auf diese Weise, wenn Sie die eindeutige Liste benötigen, können Sie einfach den kleinen Trick, wo Sie das Array in eine NSSet und dann wieder in ein Array konvertieren (das entfernt Duplikate). Wenn Sie die gesamte Liste erneut abrufen möchten, können Sie einfach das Original erneut abrufen und die Tabellenansicht erneut laden.

+0

Nach einigem Casting funktionierte es wie ein Zauber - danke! –

0

nur laut gedacht, aber wenn Sie die result zu

request.resultType = .dictionaryResultType 

wird dies wirklich funktionieren gesetzt?

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

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

Won't der fetchedObjects von [String:Any] sein?

+0

Sie haben Recht - und das ist Teil meines Problems. Wenn ich den resultType .dictionaryResultType nicht mache, funktioniert das returnDistinctResults nicht. Wenn ich den .dictionaryResultType verwende, kann ich die Tabelle nicht füllen. –

+0

Ich frage mich, wie ich verschiedene Ergebnisse ohne das WörterbuchResultType zurückgeben kann –

Verwandte Themen