Literals in Swift
A literal is a notation for representing a fixed value such as string, integer, and boolean. We can initialize types by making use of literals.
There are multiple protocols available in the Swift standard library, an example is the ExpressibleByStringLiteral
allowing us to initialize a String
using surrounding double quotes instead of using the String(init:)
method. We can all benefit from the fact that Swift is built through these protocols by adopting the protocols in our own defined types.
Just like in many other languages, Swift strings are expressed through literals surrounded by quotation marks — and can contain both special sequences (such as newlines), escaped characters, and interpolated values:
let name = "Harish"
let message = "\(name) says \"Hi!\"\nHow are you?"
print(message)
Literals in Swift are made possible by several available protocols. and while exploring, we might run into a special protocol called ExpressibleByNilLiteral
which is used to make it possible to initialize optionals using nil:
/// ExpressibleByNilLiteral
var optional: String? = nil
Like ExpressibleByNilLiteral
other standard types in swift conform to these protocols and allow us to initialize values as, which are as below:
/// ExpressibleByIntegerLiteral
var integer = 0
/// ExpressibleByStringLiteral
var string = "Hello!"
/// ExpressibleByArrayLiteral
var array = [0, 1, 2]
/// ExpressibleByDictionaryLiteral
var dictionary = ["Key": "Value"]
/// ExpressibleByBooleanLiteral
var boolean = true
Adding literal support to custom types
As above in most cases, we'll be fine by making use of the default integrated adoption of the protocols. However, it could be that we want to add custom literal support to existing types or custom types defined in our project.
For example in one of the microblogging app project I have defined structs to refer mentions and hashtags and both represents a string value at the end of the day, so have decided to add string literal support to them, and to do this, had to adopt the ExpressibleByStringLiteral
protocol for both Hashtag
and Mention
type:
struct Symbol {
enum Kind: String {
case mention = "@"
case hashtag = "#"
}
let kind: Kind
var string: String
var formattedValue: String {
return String(format: "%@%@", kind.rawValue, string)
}
}
struct Hashtag {
let symbol: Symbol
var formattedValue: String {
return symbol.formattedValue
}
init(_ string: String) {
self.symbol = Symbol(kind: .hashtag, string: string)
}
}
extension Hashtag: ExpressibleByStringLiteral {
public init(stringLiteral value: StaticString) {
self.init("\(value)")
}
}
struct Mention {
let symbol: Symbol
var formattedValue: String {
return symbol.formattedValue
}
init(_ string: String) {
self.symbol = Symbol(kind: .mention, string: string)
}
}
extension Mention: ExpressibleByStringLiteral {
public init(stringLiteral value: StaticString) {
self.init("\(value)")
}
}
let hashtag: Hashtag = "swiftlang"
print(hashtag.formattedValue)
let mention: Mention = "iharishsuthar"
print(mention.formattedValue)
In the above Swift code, the Hashtag
type is created by simple string literal and outputs "#swiftlang" in the console, and same goes for the Mention
type and which outputs "@iharishsuthar", and as we can see it just simplified the creation of Hashtag
and Mention
types.
Conclusion
Literals
are a sequence of characters (digits, letters, and other characters) that represent constant values to be stored in variables. In swift standard library typealias
of primitive types are created. Whenever we assign any value to variable with no type information, Swift uses these type aliases to determine what type to use for the expression.
Last but not least we can’t return nil from literal initializer, thus Literal protocols are good to use when we know there will be value always.