# Issues with custom string interpolation in SwiftUI Text Views

**URL:** <https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361>\
**Category:** Using Swift\
**Tags:** off-topic, swiftui\
**Created:** [April 14, 2020, 8:56am UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361 "2020-04-14T08:56:47Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [April 14, 2020, 8:56am UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/1 "2020-04-14T08:56:47Z")

</div>

I created a custom string interpolation function that allows me to pass in a string format specifier. I've noticed that, for whatever reason it does not work inside of a SwiftUI `Text` view unless I use the `init(verbatim:)` initializer. Consider this code:

```swift
import SwiftUI

struct ContentView: View {
    
    let price = 5.99
    var body: some View {
        Text("The price is $\(price, format: "%.2f")")
    }
}

extension String.StringInterpolation {

    mutating func appendInterpolation(_ value: Double, format: String) {
        appendInterpolation(String(format: format, value))
    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```

I get the error  
`Incorrect argument label in call (have '_:format:', expected '_:specifier:')`  
It seems that there's some other interpolation function using `'_:specifier:'`, but I want to use my own custom function.

If I change  
`Text("The price is $\(price, format: "%.2f")")`  
to  
`Text(verbatim: "The price is $\(price, format: "%.2f")")`  
then it works fine. Why?

**How can I implement the interpolation function in such a way that it works inside `Text` views?**

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [April 14, 2020, 12:04pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/2 "2020-04-14T12:04:36Z")

</div>

[`Text.init`](https://developer.apple.com/documentation/swiftui/text/3065754-init) uses `LocalizedStringKey`, so you need to extend the interpolation there.

Also, I’d try to avoid using a common structure like `\(double, format: format)` in case SwiftUI decides to add it unless it’s intentional, maybe add some prefix?

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [April 15, 2020, 4:26pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/3 "2020-04-15T16:26:02Z")

</div>

@Lantua Is there anyway to extend both `String` and `LocalizedStringKey` using a protocol extension? I'd prefer not to duplicate code.

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [April 15, 2020, 6:45pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/4 "2020-04-15T18:45:19Z")

</div>

> [@Peter-Schorn](#):
>
> Text("The price is $(price, format: "%.2f")")

If this is all you want, `LocalizedStringKey` can do it already, just do:

`Text("The price is $\(price, specifier: "%.2f")")`

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [April 15, 2020, 6:47pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/5 "2020-04-15T18:47:36Z")

</div>

@young But what if I want to make custom interpolation functions that work with both LocalizedStringKey and normal strings? How do I avoid writing a separate interpolation function for each?

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [April 15, 2020, 6:58pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/6 "2020-04-15T18:58:00Z")

</div>

The `Text("abcd string literal")` initializor is meant for localization as it do lookup of Localizable.strings. You might be able to extend it, but it worn't do lookup of your extension, I don't think.

If you just want your own interpolation on String, use:

`Text(verbatim: "The price is $(price, format: "%.2f")")`

This one takes a String so your custom interpolation should just work, but then you cannot localize it.

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [April 15, 2020, 7:04pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/7 "2020-04-15T19:04:41Z")

</div>

I don't care about lookups, but I also don't want to have to type the extra parameter `verbatim` every time I want to do string interpolations. I've discovered how to write a extension for localized strings and for regular strings, but I would like to know if I can write just a single function in a protocol extension so that I don't have to duplicate code. Is this possible? Currently, I have to do this. Notice that the functions are exactly the same.

```swift
public extension LocalizedStringKey.StringInterpolation {
    mutating func appendInterpolation(_ value: Double, format: String) {
        appendInterpolation(String(format: format, value))
    }
}

public extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: Double, format: String) {
        appendInterpolation(String(format: format, value))
    }
}

```

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [April 15, 2020, 7:32pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/8 "2020-04-15T19:32:40Z")

</div>

> [@Peter-Schorn](#):
>
> I don't care about lookups

In this case, then it makes no sense to extend `LocalizedStringKey.StringInterpolation`

> [@Peter-Schorn](#):
>
> but I also don't want to have to type the extra parameter `verbatim` every time I want to do string interpolation

`Text(_:)`  
`Text(verbatim:)`

are two different functions, you have to type it out so the compiler can tell what you want. It can't read you mind.

---

<div class="post-metadata">

**Author:** ![odmir](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/odmir/32/4784_2.png) [@odmir](https://forums.swift.org/u/odmir)\
**Post date:** [April 15, 2020, 11:12pm UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/9 "2020-04-15T23:12:46Z")

</div>

> [@Peter-Schorn](#):
>
> I would like to know if I can write just a single function in a protocol extension so that I don't have to duplicate code

Making a new protocol with the correct required method and extension, and then extending `LocalizedStringKeys/String.StringInterpolation` with this new protocol seems to work for me:

```swift
protocol Formattable {
    mutating func appendInterpolation(_: String)
}

extension Formattable {
    mutating func appendInterpolation(_ value: Double, format: String) {
        appendInterpolation(String(format: format, value))
    }
}

extension LocalizedStringKey.StringInterpolation: Formattable {}
extension String.StringInterpolation: Formattable {}

```

---

<div class="post-metadata">

**Author:** ![Peter-Schorn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/peter-schorn/32/11183_2.png) [@Peter-Schorn](https://forums.swift.org/u/Peter-Schorn)\
**Post date:** [April 16, 2020, 5:06am UTC](https://forums.swift.org/t/issues-with-custom-string-interpolation-in-swiftui-text-views/35361/10 "2020-04-16T05:06:14Z")

</div>

> [@Peter-Schorn](#):
>
> > [@Peter-Schorn](#):
> >
> > I don't care about lookups
> 
> In this case, then it makes no sense to extend `LocalizedStringKey.StringInterpolation`

I should've been more clear about this. What I meant was that I don't want to have to type `Text(verbatim: "abc")` everytime I want to do a string interpolation. I want to be able to just type `Text("abc")` and be able to use the same string interpolation functions as if I had just used a normal string.

@odmir has provided the exact answer that I'm looking for. Thanks Odmir!

Don't forget about how powerful protocol extensions are.
