前提:swift不同数值类型无法进行运算的操作。比如Int16的数值类型不能和Int8的数值类型做加减乘除等操作
所以在进行位运算的时候也不能用Int16的数值类型和Int8的数值类型进行与或非等操作。接下去的均以相同的类型进行运算
一、位运算
1、无符号的位运算均与C语言的操作一样,这里就不再赘述
2、有符号的位运算
1、数值的二进制设置:let initBit: Int8 = 0b00001111; 这里将二进制数值设置给initBit是正常的操作。但是我们知道在C语言中如果最高位为1则是负数,那么我们能否这样初始化呢?let initBit: Int8 = 0b10001111; 答案是不行的,在这里会提示已经溢出了。所以如果要赋值负数则应该为let initBit: Int8 = -0b00001111;
2、虽然上述的赋值运算不能在最高位设置为1来代表负数,但是当赋值完成之后,接下去的与或非移位等运算却又与无符号的位运算一致。如下所示
let bit1: Int8 = -0b00001111 // 计算机底层均是以补码的形式存在数值是:0b11110001 负数是符号位除外其他位按位取反再加1
let bit2: Int8 = 0b01111000
print(bit2 & bit1) // 112 0b01110000
print(bit2 << 1) // -16 0b11110000
3、虽然swift的加减乘除等操作正常情况下是不允许溢出,但是移位运算产生的溢出则不会抛出异常,比如: bit2 << 10; 理论上这样子的操作要溢出,但是却没问题。
二、resultBuilder
当我们要构造数组或者要在数组里面增加额外的if或者for等操作来生成一个或者多个对象是,如果用普通的方式整体的代码会晦涩难懂;而如果用resultBuilder的话,整个代码的结构则会清晰很多
比如例子:
protocol Drawable {
func draw() -> String
}
struct Line: Drawable {
var elements: [Drawable]
func draw() -> String {
return elements.map { $0.draw() }.joined(separator: "")
}
}
struct Text: Drawable {
var content: String
init(_ content: String) { self.content = content }
func draw() -> String { return content }
}
struct Space: Drawable {
func draw() -> String { return " " }
}
struct Stars: Drawable {
var length: Int
func draw() -> String { return String(repeating: "*", count: length) }
}
struct AllCaps: Drawable {
var content: Drawable
func draw() -> String { return content.draw().uppercased() }
}
View Code
let name: String? = "Ravi Patel"
let manualDrawing = Line(elements: [
Stars(length: 3),
Text("Hello"),
Space(),
AllCaps(content: Text((name ?? "World") + "!")),
Stars(length: 2),
])
print(manualDrawing.draw())
整体代码虽然看的懂,但是不够清晰,特别是AllCaps的Text((name ?? "World")操作判断 如果name存在则使用name,否则使用"World"
如果能够使用如下的方法进行调用的话,则整体的代码虽然多了一些,但是更清晰并且更符合swift的特性
func draw(@DrawingBuilder content: () -> Drawable) -> Drawable {
return content()
}
func caps(@DrawingBuilder content: () -> Drawable) -> Drawable {
return AllCaps(content: content())
}
func makeGreeting(for name: String? = nil) -> Drawable {
let greeting = draw {
Stars(length: 3)
Text("Hello")
Space()
caps {
if let name = name {
Text(name + "!")
} else {
Text("World!")
}
}
Stars(length: 2)
}
return greeting
}
let genericGreeting = makeGreeting()
print(genericGreeting.draw())
resultBuilder为上述的操作创造了可能,上面用到的特性有
1、draw后面的block 2、caps后面的block 3、caps里面的if-else 4、caps里面if 的block和else的block
只要需要应用到的这些特性均需要在resultBuilder中体现出来,如下所示
@resultBuilder
struct DrawingBuilder {
static func buildBlock(_ components: Drawable...) -> Drawable {
return Line(elements: components)
}
static func buildEither(first: Drawable) -> Drawable {
return first
}
static func buildEither(second: Drawable) -> Drawable {
return second
}
}
在caps中,假设name有值;则先调用if(通过调用first返回), 接着调用if后面的block然后再调用caps后面的block
通过caps的流程可以看出不管调用哪个,最后均需要通过block返回。所以在resultBuilder 中,buildBlock一定要构造
具体的resultBuilder使用说明可以看这个链接:https://www.cnswift.org/attributes#resultBuilder