Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift 5's Custom String Interpolation in Practice

Bas Broek
February 06, 2020

Swift 5's Custom String Interpolation in Practice

Bas Broek

February 06, 2020
Tweet

More Decks by Bas Broek

Other Decks in Programming

Transcript

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

    • RayWenderlich tech editor • iOS Platform at XING @basthomas, Copenhagen Cocoa, 06-02-2020 2
  2. 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. 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. Multiline String Literals (SE-0168) """ Hello, how are you doing

    this \(timeOfDay)? """ @basthomas, Copenhagen Cocoa, 06-02-2020 11
  5. 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. let message: LocalizableString = #"The document "\(name)" could not be

    saved."# alert.messageText = String(localized: message) @basthomas, Copenhagen Cocoa, 06-02-2020 16
  7. 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. 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. 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. 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
  11. 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
  12. 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
  13. 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
  14. 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: "[email protected]")" // <p>Find me on <a href="https://twitter.com/basthomas">@basthomas</a> // or send an email to <a href="mailto:[email protected]">[email protected]</a></p> @basthomas, Copenhagen Cocoa, 06-02-2020 34