「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战」。
Swift 的一个特性就是ExpressibleBy-Literal
协议簇(字面量)。这是一组协议,允许您通过提供一些Swift 对象来实例化对象。例如,我们可以实例化一个提供布尔值或字符串的对象。Literal是表示源代码中固定值的符号。整数、字符串、布尔值、浮点数、数组、字典都是Literal ,就像实例Array
和数组字面量(*array literal*)
是两个不同的东西,不应该混淆。对于Dictionary
也是同样的原因。
Swift 包含一系列ExpressibleByLiteral
协议,用于使用匹配的文字初始化自定义类型。
字面量
字面量指字面代表的常量值。
种类 | 示例 |
---|---|
字符串 | "joke" , hello world |
浮点型数字 | 100.3 |
整型数字 | 10 , 3 |
布尔值 | true , false |
数组 | [1, 2, 3] |
字典 | ["name": "joke"] |
空 | nil |
ExpressibleByNilLiteral
ExpressibleByNilLiteral
是当一个对象被初始化时nil
,您不希望整个对象为零,您可能有一个自定义要求,您需要考虑在其中的属性nil
显示不同的内容。但是Apple不鼓励遵循ExpressibleByNilLiteral
自定义类型。目前只有Optional
类型符合它,用于表示没有值。
struct XWNilTest {
var name: String?
var sex: String?
}
extension XWNilTest: ExpressibleByNilLiteral{
init(nilLiteral: ()) {
self.name = "Joke"
self.sex = "男"
}
}
let myStruct: XWNilTest = nil
print(myStruct.name)//XWNilTest(name: Optional("Joke"), sex: Optional("男"))
复制代码
ExpressibleByStringLiteral
ExpressibleByStringLiteral
可以使用字符串来实例化我们的对象。String
和StaticString
类型符合ExpressibleByStringLiteral
协议,使用此协议时,请确保至少实现以下init(stringLiteral:)
方法:
extension URL : ExpressibleByStringLiteral {
public init(stringLiteral value: StringLiteralType) {
guard let url = URL(string: "\(value)") else {
preconditionFailure("This url: \(value) is not invalid")
}
self = url
}
}
let url : URL = "https:www.xxx.com"
print(url)//https:www.xxx.com
复制代码
ExpressibleByIntegerLiteral
ExpressibleByIntegerLiteral
使用数字来实例化我们的对象非常容易。使用此协议时,请确保至少实现以下init(integerLiteral:)
方法:
extension Date: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd"
self = formatter.date(from: String(value)) ?? Date()
}
}
let date : Date = 19941221
print(date)//**1994-12-20 16:00:00 +0000**
复制代码
ExpressibleByFloatLiteral
标准库浮点类型——Float
,Double
都符合ExpressibleByFloatLiteral
协议。您可以通过分配浮点文字来初始化任何这些类型的变量或常量。
struct XWFloatTest: ExpressibleByFloatLiteral {
let value: Float
typealias FloatLiteralType = Float
init(floatLiteral value: Float) {
self.value = value
}
}
let num: XWFloatTest = 5.5
print(num)//**WFloatTest(value: 5.5)**
复制代码
ExpressibleByBooleanLiteral
可以用布尔值初始化true
并且false
应该符合这个协议的类型。
struct XWBoolTest: ExpressibleByBooleanLiteral {
typealias BooleanLiteralType = Bool
let boolValue: Bool
init(booleanLiteral value: BooleanLiteralType) {
self.boolValue = value
}
}
let isSucc: XWBoolTest = false
print(isSucc)
复制代码
ExpressibleByArrayLiteral
ExpressibleByArrayLiteral
遵守协议时实现由Array支持的自定义集合。
class XWArrayTest: ExpressibleByArrayLiteral {
public typealias ArrayLiteralElement = Int
let numbers: [ArrayLiteralElement]
public required init(arrayLiteral elements: ArrayLiteralElement...){
self.numbers = elements.map { $0 * $0 }
}
}
let array: XWArrayTest = [2, 4, 6]
print(array.numbers)//**[4, 16, 36]**
复制代码
ExpressibleByDictionaryLiteral
与其对应的 Array 类似,ExpressibleByDictionaryLiteral
主要用于由字典支持的自定义集合和类型。
struct HTTPHeaders {
private let headers: [String: String]
}
extension HTTPHeaders: ExpressibleByDictionaryLiteral {
init(dictionaryLiteral elements: (String, String)...) {
var headers: [String: String] = [:]
for pair in elements {
headers[pair.0] = pair.1
}
self = HTTPHeaders(headers: headers)
}
}
let headers: HTTPHeaders = ["Content-Type": "application/json"]
print(headers)//**HTTPHeaders(headers: ["Content-Type": "application/json"])**
复制代码
需要注意的是不应该将DictionaryLiteral与 Dictionary 的实例混淆。因此,不可能通过为其ExpressibleByDictionaryLiteral
分配 Dictionary 实例来初始化符合的类型。下面的代码是错误的:
let headersDictionary = ["Content-Type": "application/json"]
let anotherHeaders: HTTPHeaders = headersDictionary
//Cannot convert value of type '[String : String]' to specified type 'HTTPHeaders'
复制代码