ios - 根据表达式在 fetchrequest 中创建列

标签 ios swift uitableview core-data nsfetchedresultscontroller

总结

我希望能够根据核心数据实体的 fetchRequest 中的表达式创建一个新值。

拥有一个具有此属性的实体(简短版)

  Name              Attributes
[Course] -> {licenseStart, name, id}

我想对该实体进行 fetchResquest 并检索一个包含所有属性的字典,再加上一个基于此表达式的属性:

licenseStart.doubleValue / 1000 < NSDate().timeIntervalSince1970 ? "Actually" : "Cooming Soon"

所以结果会是:

[ "licenseStart":1,"id":3, "name":"A", "status":0, ...
  "licenseStart":2,"id":4, "name":"B", "status":0, ...
  "licenseStart":3,"id":6, "name":"B", "status":0, ...
  "licenseStart":4,"id":2, "name":"C", "status":0, ...
  "licenseStart":5,"id":1, "name":"D", "status":1, ...
  "licenseStart":6,"id":7, "name":"E", "status":1, ...
]

发布

我想问一个我几天来一直面临的问题。我尝试过的每一种方法最终都会得到一个更复杂的解决方案。

我给你解释一下情况:

我有一个 CoreData 模型,其实体具有不同的属性,其中之一是license start,这是一个 unix 时间戳数字,用于确定类(class)何时开始。

因此,当我想填充数据以创建包含类(class)的 UITableView 时,我可以毫无问题地从数据库中获取所有这些信息,我使用此 licenseStart 属性来计算基于的部分在公式上,这是 UITableView 的代码

UITableViewController

let entity = NSEntityDescription.entityForName("Course", inManagedObjectContext: managedObjectContext!)
        let req = NSFetchRequest()
        let predicate = sectionProtocol?.FRCPredicate
        let sort = [NSSortDescriptor(key: "licenseStart", ascending: true), NSSortDescriptor(key: "name", ascending: true), NSSortDescriptor(key: "courseId", ascending: true)]
        req.entity = entity
        req.sortDescriptors = sort
        req.predicate = predicate
        /* NSFetchedResultsController initialization
        a 'nil' 'sectionNameKeyPath' generates a single section */
        var aFetchedResultsController = NSFetchedResultsController(fetchRequest: req, managedObjectContext: managedObjectContext!, sectionNameKeyPath:"dateStatus", cacheName: nil)

在此之后我的结果(小例子)是这样的

[ "licenseStart":1,"id":3, "name":"A",...
  "licenseStart":2,"id":4, "name":"B",...
  "licenseStart":3,"id":6, "name":"B",...
  "licenseStart":4,"id":2, "name":"C",...
  "licenseStart":5,"id":1, "name":"D",...
  "licenseStart":6,"id":7, "name":"E",
]

我将在 UITableView 中拥有的是:

[Actually] 
  [A]
  [B]
  [B]
  [C]
[Cooming Soon]
  [D]
  [E]

那么,我现在要做的是使用 licenseStart 创建两个部分,怎么样?很简单,只需使用我的模型的一个名为 dateStatus 的属性并创建两个可能的部分使用许可证开始的结果如下:

模型类

var dateStatus : Int {
        get {
            return licenseStart.doubleValue / 1000 < NSDate().timeIntervalSince1970 ? "Actually" : "Cooming Soon"
        }
 }

因此,在我的 UITableView 中,我再次使用数据源委托(delegate)方法来填充行和部分。

问题

到目前为止一切正常。但现在我想添加一个排序选项,让用户对结果进行升序或降序排序,问题是当我排序时,即使用不同的排序选项升序:

let entity = NSEntityDescription.entityForName("Course", inManagedObjectContext: managedObjectContext!)
        let req = NSFetchRequest()
        let predicate = sectionProtocol?.FRCPredicate
        let sort = [NSSortDescriptor(key: "licenseStart", ascending: true), NSSortDescriptor(key: "name", ascending: false), NSSortDescriptor(key: "courseId", ascending: false)]
        req.entity = entity
        req.sortDescriptors = sort
        req.predicate = predicate
        /* NSFetchedResultsController initialization
        a 'nil' 'sectionNameKeyPath' generates a single section */
        var aFetchedResultsController = NSFetchedResultsController(fetchRequest: req, managedObjectContext: managedObjectContext!, sectionNameKeyPath:"dateStatus", cacheName: nil)

由于我基于 licenseStart 创建部分的方式,此提取的结果将与以前完全相同:

[ "licenseStart":1,"id":3, "name":"A",...
  "licenseStart":2,"id":4, "name":"B",...
  "licenseStart":3,"id":6, "name":"B",...
  "licenseStart":4,"id":2, "name":"C",...
  "licenseStart":5,"id":1, "name":"D",...
  "licenseStart":6,"id":7, "name":"E",
]

我将在 UITableView 中拥有的是:

[Actually] 
  [A]
  [B]
  [B]
  [C]
[Coming Soon]
  [D]
  [E]

为什么?因为 licenseStart 都是不同的,它使用 NSSortDescriptors 中的第一个元素来检索数据。这不是我想要的行为,我想要的是让这些部分的顺序与以前完全相同,但里面的元素排列不同

即:

[Actually] 
  [C]
  [B]
  [B]
  [A]
[Coming Soon]
  [E]
  [D]

可能的解决方案

我的想法是在 fetchrequest 期间创建一个新列,如果我能够计算这个表达式 licenseStart.doubleValue / 1000 < NSDate().timeIntervalSince1970 ? 0 : 1在检索数据的那一刻,我会在结果中得到这个带有 0 和 1 的新列:

[ "licenseStart":1,"id":3, "name":"A", "status":0, ...
  "licenseStart":2,"id":4, "name":"B", "status":0, ...
  "licenseStart":3,"id":6, "name":"B", "status":0, ...
  "licenseStart":4,"id":2, "name":"C", "status":0, ...
  "licenseStart":5,"id":1, "name":"D", "status":1, ...
  "licenseStart":6,"id":7, "name":"E", "status":1, ...
]

现在我可以使用此status 在 NSSortDescriptors [NSSortDescriptor(key: "status", ascending: true),NSSortDescriptor(key: "licenseStart", ascending: true), NSSortDescriptor(key: "name", ascending: true), NSSortDescriptor(key: "courseId", ascending: true)] 中创建部分升序和[NSSortDescriptor(key: "status", ascending: true),NSSortDescriptor(key: "licenseStart", ascending: false), NSSortDescriptor(key: "name", ascending: false), NSSortDescriptor(key: "courseId", ascending: false)]下降。

这会给我我想要的行为..但我一直没能找到一个好的和干净的方法来做到这一点。我尝试使用 NSExpressions 来执行此操作,但我不能将 less than 与 CoreData 提取一起使用..

此外,一个可能的解决方案是在我的数据模型中创建这个新列并在保存数据时生成这个值,但这不是一个有效的方法,因为每次用户填充时都必须将这个 licenseStart 值与当前时间戳进行比较这张表。

我在问是否有人对这个问题有一个简短的想法或一个聪明的解决方案。

在 MySQL 或 SQLite 中,基于特定值或表达式创建新列很容易,但在 coredata 中,我是新手,所以我没有看到明确的方法来做到这一点。

非常感谢。

最佳答案

我遇到过这样一种情况,我想将一些元素分开,使其位于列表的顶部,而不是基于核心数据属性。我用 fetchedResultsController 进行了提取,然后进行了一次运行以将元素放入两个数组 (O(n)) 中的一个,并按其原始排序保持排序。当元素发生变化时,我必须在我的数组中找到它们才能更改它们,但这并不像我预期的那么难。

一个更简单的解决方案可能是使用两个 fetchedResultsController。

关于ios - 根据表达式在 fetchrequest 中创建列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42830510/

相关文章:

IOS9。是否可以在应用程序中禁用 3D 触控?

ios - 连接到 Google Drive API 时出错(Swift 5)

swift - 使用swift从WebView中的列表显示PDF

ios - 滚动时自定义 UITableviewCell 缓慢且滞后

ios - MPMovieplayer 现在播放 iOS 问题

ios - 在 iOS 中关闭 View Controller 时 ContentInset 设置错误

ios - 上传存档错误 : "Missing iOS Distribution signing identity for ..."

iphone - 具有不同属性的 NSFetchRequest

ios - 在 UISearchController 中隐藏搜索栏上的取消按钮

iphone - 单击后退按钮时,ViewController 标题颜色将改变颜色