Быстрая интерполяция строк с помощью форматирования

#swift #swiftui

Вопрос:

В SwiftUI я могу использовать интерполяцию строк с параметром форматирования. Это работает в нескольких местах, например:

 struct ContentView: View {
    static let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .long
        return formatter
    }()

    let currentDate = Date()
    @State var userInput = ""
    @State var selection = ""

    var body: some View {
        Form {
            Text("This is a date: (currentDate, formatter: Self.dateFormatter)")
            Picker("This is also a date: (currentDate, formatter: Self.dateFormatter)",
                   selection: self.$selection) {
                Text("Dummy")
            }
        }
    }
}
 

Этот способ интерполяции строк, по-видимому, определен в SwiftUI, потому что, если я «перейду к определению» в Xcode, появятся следующие строки:

 public mutating func appendInterpolation<Subject>(_ subject: Subject, formatter: Formatter? = nil) where Subject : ReferenceConvertible

public mutating func appendInterpolation<Subject>(_ subject: Subject, formatter: Formatter? = nil) where Subject : NSObject
 

Когда я пытаюсь использовать эту форму интерполяции строк на игровой площадке, она завершается ошибкой:

 import SwiftUI
import Foundation

let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .long
    return formatter
}()
let date = Date()

print("Current date: (date, formatter: dateFormatter)")
 

Вышеприведенная игровая площадка завершается со следующей ошибкой:

 error: StringInterpolationWithFormatter.playground:12:41: error: extra argument 'formatter' in call
print("Current date: (date, formatter: dateFormatter)")
                                        ^~~~~~~~~~~~~
 

Почему?

Ответ №1:

Вы можете использовать formatter: аргумент в строковой интерполяции с Text , потому что Text инициализатор принимает a LocalizedStringKey , а не a String .

LocalizedStringKey определил некоторые специальные функции интерполяции строк с appendInterpolation показанными вами перегрузками (in LocalizedStringKey.StringInterpolation ), поэтому вы можете использовать formatter: аргумент с ним.

Однако в инструкции print вы просто печатаете строку, и используется строка DefaultStringInterpolation , у которой нет appendInterpolation перегрузки, которая принимает formatter: аргумент.

Просто создайте расширение DefaultStringInterpolation , чтобы добавить эту новую интерполяцию строк, если хотите:

 extension DefaultStringInterpolation {
    // signature copied from LocalizedStringKey.StringInterpolation
    mutating func appendInterpolation<Subject>(_ subject: Subject, formatter: Formatter) {
        appendInterpolation(formatter.string(for: subject)!)
    }
}
 

Ответ №2:

Сначала вам нужно создать свою собственную интерпретацию строк для строки. Подобный этому

 extension String.StringInterpolation {
    mutating func appendInterpolation(_ date: Date, formatter: DateFormatter) {
        appendLiteral(formatter.string(from: date))
    }
}
 

И теперь вы можете использовать

 let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .long
    return formatter
}()
let date = Date()

print("Current date: (date, formatter: dateFormatter)")
 

Вы можете прочитать больше о интерполяции строк здесь