基于to-many关系中的属性检索NSManagedObjects的最快方法

时间:2016-10-29 07:12:14

标签: ios swift core-data

我正在使用sqlite作为底层存储的CoreData堆栈。我的架构看起来像这样:

Data Model

图像可以包含多个标签,标签可以属于多个图像。我的用例是能够搜索与特定标签名称匹配的图像。标记的name属性已编入索引。

我在ViewController中使用FetchedResultsController来填充具有所需图像的CollectionView。最初我将谓词传递为nil但是在搜索时我需要显示相关结果,即与标签匹配的图像与指定的标签名称。下面是我的FetchedResultsController初始化方法。

func initialiseFetchedResultsControllerWith(_ predicate: NSPredicate) {

        //If the FRC is already initialised then just change the predicate and fetch again

        if fetchedResultsController != nil {
            fetchedResultsController.fetchRequest.predicate = predicate
        } else {
            let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "SMImage")
            let timestampSortDescriptor = NSSortDescriptor(key: "timestamp", ascending: false)
            fetchRequest.sortDescriptors = [timestampSortDescriptor]
            fetchRequest.predicate = predicate

            fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DataStoreController.sharedController.managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
            fetchedResultsController.delegate = self
        }

        do {
            try self.fetchedResultsController.performFetch()
        } catch {
            print("Error in fetching image obbject via FRC => \(error)")
        }

    }

我需要将一个谓词传递给FetchedResultsController来获取图像。我想到了两种方法:

  1. 获取objectIDs包含搜索字符串的所有SMTag,然后查询包含这些objectID的SMImages。

         let fetchRequest = NSFetchRequest<NSManagedObjectID>(entityName: "SMTag")
        fetchRequest.predicate = NSPredicate(format: "name contains[cd] %@", text)
        fetchRequest.resultType =  NSFetchRequestResultType.managedObjectIDResultType
        var tagIDs: Array<NSManagedObjectID>? = nil
    
         do {
         tagIDs = try DataStoreController.sharedController.managedObjectContext!.fetch(fetchRequest)
         } catch {
         print("Error in retreiving tags with names = \(error)")
         }
    
    
    
         if tagIDs != nil {
         predicate = NSPredicate(format: "tags IN %@", NSSet(array: tagIDs!))
         }
    
  2. 此方法确实返回tagID但不返回任何图像。

    1. 另一种方法是使用谓词直接搜索SMTag的图像名称:

          predicate = NSPredicate(format: "ANY tags.name contains[cd] %@", text)
      
    2. 如果你知道任何更好的方法,请建议。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

这两种方法都没有充分利用核心数据。你有多对多的关系,为什么不用呢?更好的方法是:

  1. 获取包含搜索字词的单个SMTag。这与代码片段的第一部分非常相似,只是您将获取托管对象而不是对象ID。

  2. 使用images上的SMTag关系获取与该标记相关联的所有图片。如果您有SMTag的自定义类,则类似fetchedTag.images。如果没有,那就像fetchedTag.value(forKey:"images")