CoreStore 分段列表监视器如何在运行时指定 .where 子句
CoreStore sectioned list monitor how to specify .where clause in runtime
我的初始化方法中有这段代码:
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
包含一对一关系 Muscle
(exercise.muscle
).
每个实体都有唯一的标识符属性。
我有一组肌肉标识符,我想将其用作过滤器以显示分段列表中的对象。
如何循环遍历此标识符以将 then to .where 子句添加到 CoreStore.monitorSectionedList
我可能期待这样的事情,但不是 100% 肯定只是假设:
let predicate = 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"
我看起来 coreStore 是一个很酷的核心数据包装器,'where' 方法正在幕后创建一个 NSPredicate。问题是您将谓词数组传递给需要字符串的方法。
首先将您的谓词数组变成一个谓词。使用 NSCompoundPredicate
andPredicateWithSubpredicates
(参见 https://developer.apple.com/documentation/foundation/nscompoundpredicate/1407855-init)。
接下来,不要使用格式通过字符串传递它,而是直接将其传递给 where() 子句而不使用格式一词。我相信 CoreStore 直接接受 NSPredicates 而不必从格式创建它们。
我认为这会起作用:
.where(NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates))
如果您想获取所有 muscle.id 包含在 muscleId 列表中的 ExerciseEntity,您只需使用:
let muscleIds = workout?.muscles.compactMap({ [=10=].id }) ?? []
From....
.where(Where<ExerciseEntity>(#keyPath(ExerciseEntity.muscle.id), isMemberOf: muscleIds))
这相当于一个谓词,格式为:%K IN %@, ExerciseEntity.muscle.id, muscleIds
这也适用于取反 -> NOT(%K IN %@),就像您可以在 CoreStore 中使用 !Where 一样。
复合谓词需要指定它们的链接方式。 CoreStore 一次支持 2 个谓词的 shorthand,使用逻辑运算符,例如:
Where<ExerciseEntity>(yourWhereClause) && Where<ExerciseEntity(otherWhereClause)
这相当于像这样使用 NSCompoundPredicate:
NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate])
如果您需要更复杂的连词,您也可以将该复合谓词作为参数直接传递给 where 子句。然后,您还可以将该复合谓词存储在某处,并附加另一个符合您需要的复合谓词。
我的初始化方法中有这段代码:
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
包含一对一关系 Muscle
(exercise.muscle
).
每个实体都有唯一的标识符属性。
我有一组肌肉标识符,我想将其用作过滤器以显示分段列表中的对象。
如何循环遍历此标识符以将 then to .where 子句添加到 CoreStore.monitorSectionedList
我可能期待这样的事情,但不是 100% 肯定只是假设:
let predicate = 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"
我看起来 coreStore 是一个很酷的核心数据包装器,'where' 方法正在幕后创建一个 NSPredicate。问题是您将谓词数组传递给需要字符串的方法。
首先将您的谓词数组变成一个谓词。使用 NSCompoundPredicate
andPredicateWithSubpredicates
(参见 https://developer.apple.com/documentation/foundation/nscompoundpredicate/1407855-init)。
接下来,不要使用格式通过字符串传递它,而是直接将其传递给 where() 子句而不使用格式一词。我相信 CoreStore 直接接受 NSPredicates 而不必从格式创建它们。
我认为这会起作用:
.where(NSCompoundPredicate.init(andPredicateWithSubpredicates: predicates))
如果您想获取所有 muscle.id 包含在 muscleId 列表中的 ExerciseEntity,您只需使用:
let muscleIds = workout?.muscles.compactMap({ [=10=].id }) ?? []
From....
.where(Where<ExerciseEntity>(#keyPath(ExerciseEntity.muscle.id), isMemberOf: muscleIds))
这相当于一个谓词,格式为:%K IN %@, ExerciseEntity.muscle.id, muscleIds
这也适用于取反 -> NOT(%K IN %@),就像您可以在 CoreStore 中使用 !Where 一样。
复合谓词需要指定它们的链接方式。 CoreStore 一次支持 2 个谓词的 shorthand,使用逻辑运算符,例如:
Where<ExerciseEntity>(yourWhereClause) && Where<ExerciseEntity(otherWhereClause)
这相当于像这样使用 NSCompoundPredicate:
NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate])
如果您需要更复杂的连词,您也可以将该复合谓词作为参数直接传递给 where 子句。然后,您还可以将该复合谓词存储在某处,并附加另一个符合您需要的复合谓词。