CoreStore分段列表监视器如何在运行时指定.where子句

时间:2019-08-30 18:44:26

标签: ios swift core-data nspredicate corestore

我的init方法中包含以下代码:

self.monitor = CoreStore.monitorSectionedList(
        From<ListEntityType>()
            .sectionBy(#keyPath(ListEntityType.muscle.name)) { (sectionName) -> String? in
                return "\(String(describing: sectionName)) years old"
            }
            .orderBy(.ascending(#keyPath(ListEntityType.muscle.name)), .ascending(\.name))
    )

我想在运行时以某种方式将其添加到此监视器.where中。

ListEntityType是称为Exercise的实体的类型别名。因此,每个Exercise都包含一对一的关系Muscleexercise.muscle)。

每个实体都有唯一的标识符属性。

我有一组肌肉标识符,我希望将其用作过滤器以显示分段列表中的对象。

如何循环遍历这些标识符,然后将它们添加到CoreStore.monitorSectionedList

的.where子句中

我可能期望这样的事情,但不能百分百确定只是一个假设:

let谓词= NSPredicate(格式:“%K = $ ARGUMENT”)

    var predicates = [NSPredicate]()

    if let muscles : [MuscleGroupEntity] = workout?.muscles.toArray() {
        for muscle in muscles
        {
            let myNewPredicate = predicate.withSubstitutionVariables(["ARGUMENT" : muscle.id])
            predicates.append(myNewPredicate)
        }
    }

    self.monitor = CoreStore.monitorSectionedList(
        From<ListEntityType>()
            .sectionBy(#keyPath(ListEntityType.muscle.name)) { (sectionName) -> String? in
                return "\(String(describing: sectionName)) years old"
            }
            .where(format:"%K = %@", argumentArray: predicates)
            .orderBy(.ascending(#keyPath(ListEntityType.muscle.name)), .ascending(\.name))
    )

此代码因错误而崩溃:

-[NSComparisonPredicate rangeOfString:]: unrecognized selector sent to

我猜这是我发现here的谓词所引起的,但不确定如何正确使用它

编辑过的MartinM评论:

我的ExerciseEntity具有肌肉属性。

如果我只想用一根肌肉ID进行所有锻炼,那很简单:

.where(format:"%K = %@", #keyPath(ExerciseEntity.muscle.id), "id_12345")

但是我想指定更多的肌肉并在运行时定义它们。我需要某种方式来了解格式是什么,参数是什么,以及如何传递标识符数组,而不只是一个"id_12345"

2 个答案:

答案 0 :(得分:1)

如果您要获取所有其Muscle.id包含在muscleIds列表中的exerciseEntity,只需使用:

let muscleIds = workout?.muscles.compactMap({ $0.id }) ?? []
From....
   .where(Where<ExerciseEntity>(#keyPath(ExerciseEntity.muscle.id), isMemberOf: muscleIds))

相当于谓词,其格式为:%K IN%@,ExerciseEntity.muscle.id,muscleIds

这对否定也有效-> NOT(%K IN%@),与您可以在CoreStore中使用!Where一样。

复合谓词需要指定如何链接。 CoreStore使用逻辑运算符,一次支持两个谓词的简写,例如:

Where<ExerciseEntity>(yourWhereClause) && Where<ExerciseEntity(otherWhereClause)

这等效于像这样使用NSCompoundPredicate:

NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate])

如果需要更复杂的连接,也可以将该复合谓词直接作为参数传递给where子句。然后,您还可以将该复合谓词存储在某个位置,并附加另一个适合您需要的复合谓词。

答案 1 :(得分:0)

我看起来corestore是一个很酷的核心数据包装器,并且“ where”方法在幕后创建NSPredicate。问题在于您要将谓词数组传递给需要字符串的方法。

首先将您的谓词数组转换为单个谓词。使用NSCompoundPredicate andPredicateWithSubpredicates(请参阅https://developer.apple.com/documentation/foundation/nscompoundpredicate/1407855-init)。

下一步,与其直接使用格式传递字符串,不如将其直接传递给where()子句而不使用单词格式。我相信CoreStore可以直接接受NSPredicates,而不必从一种格式创建它们。

我认为这会起作用:

 .where(NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates))