Swift 5's Custom String Interpolation in Practice

79fe3c13c618a61329298bdd6a86ec42?s=47 Bas Broek
February 06, 2020

Swift 5's Custom String Interpolation in Practice

79fe3c13c618a61329298bdd6a86ec42?s=128

Bas Broek

February 06, 2020
Tweet

Transcript

  1. 2.

    Who am I • Swift Weekly Brief • Contravariance (stickers)

    • RayWenderlich tech editor • iOS Platform at XING @basthomas, Copenhagen Cocoa, 06-02-2020 2
  2. 5.

    NSString *name = @"Bas"; [NSString stringWithFormat:@"Hello, %@", name]; [NSString stringWithFormat:@"%.2f",

    9.0234]; [NSString stringWithFormat: @"Hello %@, how are you doing this %@? %@", @"Bas", @"evening", @"Great!" ]; @basthomas, Copenhagen Cocoa, 06-02-2020 5
  3. 7.

    let name = "Bas" "Hello, \(name)" String(format: "%.2f", 9.0234) //

    "Hello \(name), how are you doing this \(timeOfDay)?" @basthomas, Copenhagen Cocoa, 06-02-2020 7
  4. 11.

    Multiline String Literals (SE-0168) """ Hello, how are you doing

    this \(timeOfDay)? """ @basthomas, Copenhagen Cocoa, 06-02-2020 11
  5. 12.

    String Literal Delimiters (SE-0200) // before "\"Did you put your

    name into the Goblet of Fire, Harry?\" he asked calmly." // after #""Harry! Did you put your name in the Goblet of Fire?!""# @basthomas, Copenhagen Cocoa, 06-02-2020 12
  6. 16.

    let message: LocalizableString = #"The document "\(name)" could not be

    saved."# alert.messageText = String(localized: message) @basthomas, Copenhagen Cocoa, 06-02-2020 16
  7. 18.

    extension String.StringInterpolation { mutating func appendInterpolation(_ error: Error) { appendLiteral(error.localizedDescription)

    } } fatalError( "Something went wrong: \(ConnectionError.invalidRequest)" ) @basthomas, Copenhagen Cocoa, 06-02-2020 18
  8. 20.

    extension String.StringInterpolation { mutating func appendInterpolation( number: Double, formatter: NumberFormatter

    ) { appendInterpolation( ifNotNil: formatter.string(from: NSNumber(value: number)) ) } } let priceFormatter = NumberFormatter() priceFormatter.numberStyle = .currency "\(number: 100.1234, formatter: priceFormatter)" @basthomas, Copenhagen Cocoa, 06-02-2020 20
  9. 22.

    extension String.StringInterpolation { mutating func appendInterpolation(private: String) { #if DEBUG

    appendLiteral(`private`) #else appendLiteral("@@@") #endif } } let name = "Bas" let password = "Broek" print("User \(name) has password \(private: password)") @basthomas, Copenhagen Cocoa, 06-02-2020 22
  10. 24.
  11. 25.

    extension String.StringInterpolation { mutating func appendInterpolation( dictionary: Dictionary<AnyHashable, Any>?, default:

    @autoclosure () -> String = "nil" ) { if let dictionary = dictionary { appendLiteral(String(describing: dictionary)) } else { appendLiteral(`default`()) } } } "\(dictionary: properties)" @basthomas, Copenhagen Cocoa, 06-02-2020 25
  12. 27.

    extension String.StringInterpolation { mutating func appendInterpolation( number: Int, maximum: @autoclosure

    () -> Int ) { let max = maximum() if number > max { appendLiteral("\(max)+") } else { appendLiteral("\(number)") } } } "\(number: number, maximum: maxBadgeCount)" @basthomas, Copenhagen Cocoa, 06-02-2020 27
  13. 31.

    struct BadgeCount: CustomStringConvertible { let value: Int var maximum =

    99 var description: String { if value > maximum { return "\(maximum)+" } else { return "\(value)" } } } "\(BadgeCount(value: 123, maximum: 99))" "\(BadgeCount(value: 123))" @basthomas, Copenhagen Cocoa, 06-02-2020 31
  14. 33.

    struct HTMLComponent: ExpressibleByStringLiteral, ExpressibleByStringInterpolation, CustomStringConvertible { struct StringInterpolation: StringInterpolationProtocol {

    var output = "" init(literalCapacity: Int, interpolationCount: Int) { output.reserveCapacity(literalCapacity * 2) } mutating func appendLiteral(_ literal: String) { output.append(literal) } mutating func appendInterpolation(twitter: String) { output.append("<a href=\"https://twitter.com/\(twitter)\">@\(twitter)</a>") } mutating func appendInterpolation(email: String) { output.append("<a href=\"mailto:\(email)\">\(email)</a>") } } let description: String init(stringLiteral value: String) { description = "<p>\(value)</p>" } init(stringInterpolation: StringInterpolation) { self.init(stringLiteral: stringInterpolation.output) } } @basthomas, Copenhagen Cocoa, 06-02-2020 33
  15. 34.

    struct StringInterpolation: StringInterpolationProtocol { var output = "" init(literalCapacity: Int,

    interpolationCount: Int) { output.reserveCapacity(literalCapacity * 2) } mutating func appendLiteral(_ literal: String) { output.append(literal) } mutating func appendInterpolation(twitter: String) { output.append("<a href=\"https://twitter.com/\(twitter)\">@\(twitter)</a>") } mutating func appendInterpolation(email: String) { output.append("<a href=\"mailto:\(email)\">\(email)</a>") } } let html: HTMLComponent = "Find me on \(twitter: "basthomas") or send an email to \(email: "bas@basbroek.nl")" // <p>Find me on <a href="https://twitter.com/basthomas">@basthomas</a> // or send an email to <a href="mailto:bas@basbroek.nl">bas@basbroek.nl</a></p> @basthomas, Copenhagen Cocoa, 06-02-2020 34