SwiftUI通过关系搜索核心数据



我有一个SwiftUI应用程序,它具有SwiftUI生命周期,并将数据持久化到核心数据中。我使用Xcode 14.0.1和iOS 16创建NavigationSplitView架构。这一切都很好。我已将.searchable添加到主列表中,并且能够进行搜索实体中的实体字符串字段,但我希望在中包含字符串字段

假设我有一个实体Trip,具有名称、描述和评论属性-所有字符串。我创建了一个searchResults变量,并在列表中使用结果。这适用于讨论的领域。

var searchResults: [Trip] {
if searchText.isEmpty {
return Array(tripsFetched)
} else {
return Array(tripsFetched).filter {
$0.wrappedTripName.lowercased().contains(searchText.lowercased())
||
$0.wrappedTripDescription.lowercased().contains(searchText.lowercased())
||
$0.wrappedComment.lowercased().contains(searchText.lowercased())
}//filter
}//if else
}//var search results

现在让我们假设我在Trip和实体Site之间有一个一对多的关系,并说站点具有siteName和siteDescription的字符串属性。我没能在Site对象的NSSet上添加一个迭代以查找searchText。我做了包括以下内容在内的多次尝试都没有成功。

||
$0.sites?.allObjects(where: $0.wrappedSiteName.contains(searchText.lowercased()))

如有任何指导,我们将不胜感激。

对于搜索,我们在获取请求上使用nsPredicate属性。

您需要一个或谓词,使用contains关键字表示文本,使用equals表示对象或关系的id,但本页显示了配置它的所有不同方式:

https://developer.apple.com/documentation/foundation/nspredicate

这个页面上有一个SwiftUI示例:

https://developer.apple.com/documentation/swiftui/fetchrequest/configuration

.onChange(of: query) { value in
quakes.nsPredicate = query.isEmpty
? nil
: NSPredicate(format: "place CONTAINS %@", value)
}

对于其他人来说,malhal是正确的。您可以创建一个复合谓词来搜索一对多关系。重要的部分是他的链接中引用的语法使用ANY关键字。这是一个例子:

func cdSearchQuery(searchText: String) {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = Trip.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "tripName", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]

let predicateTrip = NSPredicate(format: "tripName CONTAINS[cd] %@ || tripDescription CONTAINS[cd] %@ || tripComment CONTAINS[cd] %@ || tripCompanions CONTAINS[cd] %@", searchText, searchText, searchText, searchText)

//for the to-many attributes, use the ANY keyword
let predicateSite = NSPredicate(format: "ANY sites.siteName CONTAINS[cd] %@ || sites.siteDescription CONTAINS[cd] %@ || sites.siteLocation CONTAINS[cd] %@", searchText, searchText, searchText )

let predicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicateTrip, predicateSite])

fetchRequest.predicate = predicate

do {
let results = try context.fetch(fetchRequest)

//for testing - remove and send results to a Published array
if let tripArray = Array(results) as? [Trip] {
for t in tripArray {
print("included  is (String(describing: t.tripName))")
}
}

} catch {
print("Error retrieving compound predicate")
}
}//cd search

最新更新