ios – Automatically map an instance to one of its properties based on the inferred type in Swift


I find the compositional syntax of SwiftUI very intuitive and would like to use a similar approach for composing/modifying URLs. Here’s what I have in mind:

struct URLTemplate {
    let url: String
}

A template url might look something like this:

https://myserver.com/resource.jpg?width={width}

Now I might want to modify this URL as follows:

urlTemplate
  .width(400)        // replace the stencil → https://myserver.com/resource.jpg?width=400
  .format(.portrait) // append a parameter: &format=portrait
  .withWatermark()   // append a parameter: &watermark=true

To accomplish this, I would add extension functions on URLTemplate as follows:

extensions URLTemplate {
    func width(_ width: Int) -> URLTemplate { ... }
    func format(_ format: Format) -> URLTemplate { ... }
    func withWatermark() -> URLTemplate { ... }
}

Each of these functions would modify the url and wrap it in a new URLTemplate instance. Works.

The problem is on the caller side:

In the end, I want to have a URL, not a URLTemplate, because that’s what I use to make requests. Then why not just use a URL instance in the first place instead of this custom type? Well, because I need some other information for making these URL modifications that each modifier needs to know.

I could of course just extract the modified URL in the end like this:

urlTemplate
  .width(400)
  .format(.portrait)
  .withWatermark()
  .url                         // ← here

but this is super annoying as it leads to redundant boilerplate code as I would need to do this every time I want to use a URL to make some request.

So what I would wish for is some kind of automagic type inference whenever a URL is expected. When the compiler cannot infer a concrete type, the following expression would return a URLTemplate:

let urlTemplate = urlTemplate
  .width(400)
  .format(.portrait)
  .withWatermark()             // → returns self (type: URLTemplate)

However, when the compiler infers a URL type from the context, it should automatically understand that a URL is expected and implicitly return the url instead:

let url: URL = urlTemplate     // notice the explicit type annotation
  .width(400)
  .format(.portrait)
  .withWatermark()             // → implicitly returns self.url (type: URL)

Is there a feature like this in Swift and if not, can I somehow build this kind of behavior on my own using existing Swift language features?

Note: It should be obvious that I want to be able to use an arbitrary number of modifiers, for example, just omit the withWatermark() modifier above. So in this case, urlTemplate.width(400).format(.portrait) should also be interpreted as a URL when a URL type is inferred.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img