Closed NicFontana closed 1 year ago
Hi @NicFontana ,
Thank you for your feedback.
I suppose, you are using the Hits
component. The business logic of hits management is handled in the HitsInteractor component.
To use it, you might define the Record
object which might conform to Codable
protocol.
Let's break down the cases that seem problematic to you.
Images URLs: image URLs are stored in my index as strings, so in my hit's struct I do have String instances. What if I want to work with a URL property instead?
The URL
type conforms to Codable
protocol. So, if you define a property of URL
type in your Codable
structure, it will be seamlessly decoded, if the provided string is a valid URL. This also works for an array of urls since, an Array
of Codable
values conforms to Codable
protocol automatically.
struct Model: Codable {
let imageURLs: [URL]
}
Merged properties: my index data model has two (or more) properties that I want to merge in a single one, e.g. let city: String and let region: String that I want to merge in a single let location: String
The easiest way to achieve it, is to introduce a computed variable to your data Model:
struct Model: Codable {
let city: String
let region: String
var location: String {
"\(city), \(region)"
}
}
If you don't want to recalculate the location
on each read access, you can declare it as a lazy
variable:
struct Model: Codable {
let city: String
let region: String
lazy var location: String = {
"\(city), \(region)"
}()
}
By doing this, you will avoid the decoding boilerplate.
For more complex cases you can compose nested data models:
struct RawModel: Codable {
let city: String
let region: String
}
struct Model: Codable {
let location: String
init(from decoder: Decoder) throws {
let rawModel = RawModel(from: decoder)
self.location = "\(rawModel.city), \(rawModel.region)"
}
}
let hitsInteractor: HitsInteractor<Model> = ...
As you can see, the power of Swift allows you to introduce the transformations you need without additional layer of complexity on the InstantSearch side. I hope it answers your question. If you have other use-cases for which these approaches don't work, please share them, I'd be happy to help.
Hello @VladislavFitz
thanks for your suggestions, I really appreciated. I've been able to solve the issue by leveraging the init(from decoder: Decoder) throws
you mentioned in the last example.
I close the issue.
Is your feature request related to a problem? Please describe 🙏 I am working on a SwiftUI app. Let's consider a simple situation where I need to show a list of search results after the user provided a search text. I am using the
HitsList
component to display the results.My index data model doesn't fit my view's data model, for instance:
String
instances. What if I want to work with aURL
property instead?let city: String
andlet region: String
that I want to merge in a singlelet location: String
Describe the solution you'd like 🤔 I would like to have the possibility to provide a mapping closure that maps my index data model to a custom data model, so when the fetch happens the items inside
HitsPage
can be transformed and stored following my custom data model definition.Describe alternatives you've considered ✨ I have considered a couple of alternatives:
Apply the mapping closure inside my view for each hits Although it should works, the closure would be executed each the view re-render, so it's not the best solution considering the performance.
Provide a custom JSON decoder that does all the transformations needed Maybe this is the best solution at the moment, but it's not very friendly as a lot of boilerplate code is required.
Have ever considered this? Do you have any suggestions?
Thanks a lot, Niccolò