Reputation: 413
I'm trying to search through a list of bookmarks by name stored in Core Data but I'm getting this error next to 'return items' in var searchResults
"Cannot convert return expression of type 'FetchedResults <MyBookmark to return type '[String]'"
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \MyBookmark.name, ascending: true)], animation: .default)
private var items: FetchedResults<MyBookmark>
@State private var searchText = ""
ForEach(searchResults, id: \.self) { myBookmark in
Text(myBookmark.name!)
Text(myBookmark.url!)
}
.searchable(text: $searchText)
var searchResults: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
}
MyBookmark
@objc(MyBookmark)
public class MyBookmark: NSManagedObject, BaseModel {
static var all: NSFetchRequest<MyBookmark> {
let request: NSFetchRequest<MyBookmark> = MyBookmark.fetchRequest()
request.sortDescriptors = []
return request
}
}
extension MyBookmark {
@nonobjc public class func fetchRequest() -> NSFetchRequest<MyBookmark> {
return NSFetchRequest<MyBookmark>(entityName: "MyBookmark")
}
@NSManaged public var name: String?
@NSManaged public var url: String?
}
extension MyBookmark : Identifiable {
}
This is for a macOS app
Upvotes: 1
Views: 1506
Reputation: 51882
You need to execute your fetch request again when the search filter changes. To do that you need to set the predicate of the fetch request.
Add a new property to handle this
var query: Binding<String> {
Binding {
searchText
} set: { newValue in
searchText = newValue
if newValue.isEmpty {
items.nsPredicate = NSPredicate(value: true)
} else {
items.nsPredicate = NSPredicate(format: "name CONTAINS[cd] %@", newValue) }
}
}
And then use the .searchable
modifier together with this property
var body: some View {
ForEach {
//...
}
.searchable(text: query)
}
Upvotes: 2
Reputation: 4006
That var must return an array of String
, but you are returning the array items
, which is an array of type MyBookmark
.
Solution: convert the array to a type of [String]
.
Replace that variable with:
var searchResults: [String] {
if searchText.isEmpty {
return items.compactMap { $0.name }
} else {
return items.compactMap { $0.name }.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
}
Upvotes: 2