How to write an extension for NSFetchedResultsController in Swift 4

前端 未结 3 1333
有刺的猬
有刺的猬 2021-01-12 05:45

I\'m trying to write a simple extension to the NSFetchedResultsController class in Swift 4.

Here\'s my first attempt - which worked in Swift 3:

3条回答
  •  深忆病人
    2021-01-12 06:13

    We ended up with subclass (Swift 4). Idea behind - pass type as argument. Rest of setup operates NSManagedObject type in order to work around compile errors.

    public class FetchedResultsController: NSFetchedResultsController {
    
       public convenience init(fetchRequest: NSFetchRequest, context: NSManagedObjectContext, _: T.Type) {
          self.init(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
       }
    
       public var numberOfSections: Int {
          return sections?.count ?? 0
       }
    
       public var numberOfFetchedEntities: Int {
          return fetchedObjects?.count ?? 0
       }
    
       public func entity(at indexPath: IndexPath) -> T {
          if let value = object(at: indexPath) as? T {
             return value
          } else {
             fatalError()
          }
       }
    
       public func entity(at row: Int) -> T {
          let ip = IndexPath(item: row, section: 0)
          return entity(at: ip)
       }
    
       public var fetchedEntities: [T] {
          let result = (fetchedObjects ?? []).compactMap { $0 as? T }
          return result
       }
    }
    

    Extensions:

    extension Requests {
    
       public static func all(_: T.Type) -> NSFetchRequest {
          let request = NSFetchRequest(entityName: T.entityName)
          return request
       }
    
       public static func ordered(by: String, ascending: Bool, _: T.Type) -> NSFetchRequest {
          let request = NSFetchRequest(entityName: T.entityName)
          request.sortDescriptors = [NSSortDescriptor(key: by, ascending: ascending)]
          return request
       }
    
    }
    
    
    extension NSManagedObject {
    
        public static var entityName: String {
            let className = NSStringFromClass(self) // As alternative can be used `self.description()` or `String(describing: self)`
            let entityName = className.components(separatedBy: ".").last!
            return entityName
        }
    
        public static var entityClassName: String {
            let className = NSStringFromClass(self)
            return className
        }
    
    }
    

    Usage:

    extension ParentChildRelationshipsMainController {
    
       private func setupFetchedResultsController() -> FetchedResultsController {
          let request = DB.Requests.ordered(by: #keyPath(IssueList.title), ascending: true, IssueList.self)
          let result = FetchedResultsController(fetchRequest: request, context: PCDBStack.shared.mainContext, IssueList.self)
          return result
       }
    }
    
    extension ParentChildRelationshipsMainController: NSTableViewDataSource, NSTableViewDelegate {
    
       func numberOfRows(in tableView: NSTableView) -> Int {
          return frController.numberOfFetchedEntities
       }
    
       func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
          let rowID = NSUserInterfaceItemIdentifier("rid:generic")
          let item = frController.entity(at: row)
          // ...
       }
    }
    

提交回复
热议问题