Understanding Swift Collection Protocols: StringProtocol, CustomStringConvertible, and Related Literals
This article explores Swift's collection‑type protocols, focusing on StringProtocol and related protocols such as CustomStringConvertible, CustomDebugStringConvertible, LosslessStringConvertible, and various ExpressibleBy… literals, providing code examples and explanations of their usage in mobile development.
This article is the second part of a series analyzing Swift collection‑type protocols, with a focus on string‑related protocols.
StringProtocol abstracts the behavior of strings as collections of characters, enabling methods like uppercased() , lowercased() , and comparison operators. Both String and Substring conform to this protocol, allowing direct equality checks without conversion.
let helloSwift = "Hello Swift"
let swift = helloSwift[helloSwift.index(helloSwift.startIndex, offsetBy: 6)...]
// comparing a substring to a string
swift == "Swift" // trueThe protocol is also used as a parameter type for functions such as init(text: StringProtocol) , which lets callers avoid explicit type conversions.
CustomStringConvertible & CustomDebugStringConvertible provide custom textual representations for printing. The article lists the functions associated with each protocol:
Function
Protocol
Required Property
CustomStringConvertible
description
debugPrint
CustomDebugStringConvertible
debugDescription
dump
CustomReflectable
customMirror
Example of implementing CustomStringConvertible for a BankCard struct:
struct BankCard {
let bankName: String
let cardNumber: Int
}
let bankcard = BankCard(bankName: "CBC", cardNumber: 123232324565)
extension BankCard: CustomStringConvertible {
var description: String { "\(self.bankName) \(self.cardNumber)" }
}
print(bankcard) // CBC 123232324565Similarly, implementing CustomDebugStringConvertible provides a multi‑line debug description:
extension BankCard: CustomDebugStringConvertible {
var debugDescription: String {
"""
BankName: \(self.bankName)
CardNumber: \(self.cardNumber)
"""
}
}The dump function prints detailed, hierarchical representations of values, useful for large collections:
let names = ["apple", "orange", "banana"]
dump(names)
let iPhones = ["iPhoneX": 9688, "iPhone8 plus": 7888, "iphone8": 6888]
dump(iPhones)LosslessStringConvertible allows lossless conversion between a type and its string representation. Types such as Int , Bool , Double , etc., conform to this protocol. An example implementation for a FlightCode type shows how to parse and reconstruct the value:
extension FlightCode: LosslessStringConvertible {
public init?(_ description: String) {
let components = description.split(separator: " ")
guard components.count == 2,
let airlineCode = components.first,
let number = components.last,
let flightNumber = Int(number) else { return nil }
self.airlineCode = String(airlineCode)
self.flightNumber = flightNumber
}
}
let flight = FlightCode(airlineCode: "AA", flightNumber: 1)
String(flight) // "AA 1"
FlightCode(String(flight)) // FlightCode(airlineCode: "AA", flightNumber: 1)The article also covers the literal protocols ExpressibleByUnicodeScalarLiteral , ExpressibleByExtendedGraphemeClusterLiteral , and ExpressibleByStringLiteral , showing how to create values directly from string literals:
let unicodeScalar: Unicode.Scalar = "A"
let character: Character = "A"
let string: String = "A"It explains extended grapheme clusters, demonstrating that a single Swift Character can represent composed or decomposed Unicode sequences, such as the character "é".
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // éFinally, the article shows how to make existing types conform to literal protocols, e.g., extending URL to be initializable from a string literal, and introduces ExpressibleByStringInterpolation , which enables custom interpolation behavior.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.