Swift - 运算符 | 断言 | 先决条件

运算符

1 - Swift 所支持的运算

① 赋值         =

② 复合赋值       +=   -=

② 算术             +    -   *   /

③ 求余             %

④ 自增/自减     ++   --

⑥ 比较运算       ==   !=   >   <   >=   <=

⑦ 逻辑运算       &&   ||   !

⑧ 三目运算       ? :           注:同 C 语言一样,它是 Swift 中唯一的三目运算

⑨ 范围运算       ..<    ...

⑩ 溢出运算       &+   &-   &*   &/   &%

注:跟 C、OC 不一样的是:Swift 的赋值运算符没有返回值

var A = 10
var B = 100
// 编译不通过:A = B 并不会返回具体的值
if(A = B){

}

2 - 元组:Swift 增加了 OC 中没有的高阶数据类型,比如元组,它可以创建或者传递一组数据,当作为函数的返回值时就可以用一个元组返回多个值

注:Swift 标准库只能比较 7 个以内元素的元组比较函数,如果你的元组元素超过 7 个时就需要自己实现比较运算符

// 元组:元组内的值可以是任意类型,并不要求是相同类型
let(x,y,z) = (1,2,"6") // x = 1   y = 2  z = "6"

// 标准写法:可以明确指定元素的类型
var httpCode0: (String,Float,Int) = ("Lee",172.0,32)

// 将一个元组的内容分解成单独的常量和变量
let httpError = (404, "Not Found")
let (statusCode, statusMessage) = httpError
print("The status code is \(statusCode)")       // The status code is 404
print("The status message is \(statusMessage)") // The status message is Not Found

// 如果你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线 _ 标记
let (justTheStatusCode, _) = httpError
print("The status code is \(justTheStatusCode)")// The status code is 404

// 可通过下标来访问元组中的单个元素
print("The status code is \(httpError.0)")   // The status code is 404
print("The status message is \(httpError.1)")// The status message is Not Found

// 可在定义元组的时候给单个元素命名,比如 (200,"OK")
let http200Status = (statusCode: 200, description: "OK")
// 这时候就可以通过名字来获取这些元素的值
print("The status code is \(http200Status.statusCode)")     // The status code is 200
print("The status message is \(http200Status.description)") // The status message is OK


// 如果两个元组的元素相同且长度相同,元组就可以被比较
(1, "zebra") < (2, "apple")   // true,因为 1 小于 2
(3, "apple") < (3, "bird")    // true,因为 3 等于 3,但是 apple 小于 bird
(4, "dog") == (4, "dog")      // true,因为 4 等于 4,dog 等于 dog

3 - 算术运算

// 加减乘除
1 + 2
5 - 3
2 * 3
10.0 / 2.5
// + 也可以拼接字符串
"http://" + "www.baidu.com"  //  "http://www.baidu.com"

//-------------------------------------------

// 正号、负号:正、负号写在操作数之前,中间没有空格
// 负号
var minusNumber01 = 10
var minusNumber02 = -minusNumber01
print(minusNumber02)// -10

// 编译报错:UInt8 是无符号型
// let cannotBeNegative: UInt8 = -1

// 正号:其实没什么作用,只是跟负号运算作对称的效果
var plusNumber01 = +minusNumber02
print(plusNumber01) // -10
var plusNumber02 = -minusNumber02
print(plusNumber02) // 10

//-------------------------------------------

// 和 C 一样:结果只跟 % 左值有关
print(9 % 4)   // 1
print(-9 % 4)  // -1
print(9 % -4)  // 1
print(-9 % -4) // -1

// 过去 Swift 中的取模运算符对任何数值类型都是有效的,不管是整型还是浮点型
// 在 Swift3 中取余算法是不能作用于浮点型的,要调用 truncatingRemainder 方法
let value1 = 5.5
let value2 = 2.2
let result = value1.truncatingRemainder(dividingBy: value2)
let resultB = value1/value2
print(result)   // 1.0999999999......
print(resultB)  // 2.5

4 - Bool 类型:在 Swift 中 Bool 只有 true 和 false 两个值;而在 OC、C 中则是 YES/非0、NO/0 

// if 语句的条件必须是 Bool 类型的值
var boolValue : Bool = true
if boolValue{
     print("You are true")
}

// Bool 不能被比较
// 这也意味着存有布尔类型的元组不能被比较
print(("blue", -1) < ("purple", 1) )    // true
// ("blue", false) < ("purple", true)   // 编译错误

5 - 三目运算:三目运算符的条件必须是 Bool 类型的值

// 编译错误
let a = 10
let c = a ? 100 : 200

// 正确
let c = a != 0 ? 100 : 200
let e = false ? 100 : 200

6 - 区间运算:用来表示一个范围,有两种类型的范围运算符

① 闭合范围运算符:   a...b  表示 [a, b]

② 半闭合范围运算符:a..<b  表示 [a, b)

for number05 in 2...6{
    print(number05)
// 2,3,4,5,6 }

7 - 溢出运算

① 每种数据类型都有自己的取值范围,默认情况下一旦赋了一个超出取值范围的数值就会产生编译或者运行时错误

// crash
let x = UInt8.max
let y = x + 1

② Swfit 为整型计算提供了五个 & 开头的溢出运算符,能够对超出取值范围的数值进行灵活处理。值溢出的问题不管是有符号型还是无符号型都会存在

无符号型值溢出

let x = UInt8.max
let y = x &+ 1 // 上溢
print(y)       // 0

let x = UInt8.min
let y = x &- 1// 下溢
print(y)      // 255

有符号型值溢出

let x = Int8.min // -128
let y = x &- 1   // 127

除零溢出:默认情况下一个数除于 0 或者对 0 求余数,编译器会直接报错

let x = 10
let y = x / 0 // 报错
let z = x % 0 // 报错

8 - 可选类型

① 任何类型的可选状态都可以被设置为 nil

// 可选类型:需要感叹号来获取值
let possibleString: String? = "An optional string."
// 在强制解析值之前,一定要确定可选包含一个非 nil 的值
let forcedString: String = possibleString!

// 隐式可选类型:你可以把隐式可选类型当做一个可以自动解析的可选类型
let assumedString: String! = "An implicitly unwrapped optional string."
// 不再需要解析,直接使用
let implicitString: String = assumedString

// 如果你声明一个可选常量或者变量但是没有赋值,它们会自动置 nil
var surveyAnswer: String?  // nil

// 如果一个变量可能变成 nil 的话请不要使用隐式解析可选类型
// 因为获取一个不存在的可选值会导致运行时错误
let demoNilA: String? = nil
let demoNilB: String = demoNilA! // 编译通过,运行则crash

// 可选类型可用来判断它是否包含值
// 如果可选类型有值,它将不等于 nil
if possibleString != nil {
    print("possibleString contains some String value.")// 会执行此行代码
}

// 可在可选绑定中使用可选类型来检查并解析它的值
// 其实就是判断 definiteString 是否是 nil
if let definiteString = possibleString {
    print(definiteString) // 会执行此行代码
}

// 编译不通过:非 Bool 类型
let definiteStringII = possibleString!
if definiteStringII {
     print(definiteStringII)
}

② 类型转换:其实质就是把将要被转换的数据推测为所要转换的类型

let possibleNumber = "123"
// convertedNumber 被推测为类型 "Int?" 或类型 "optional Int"
let convertedNumber = Int(possibleNumber)
// 因为该构造器可能会失败,所以它返回一个可选类型,而不是一个 Int
print(convertedNumber as Any) // Optional(123)

let someNumber = "yes"
let resNumber01 = String(someNumber)
print(resNumber01) // yes
let resNumber02 = Int(someNumber)
print(resNumber02)// nil

9 - 空盒运算:a ?? b 将对可选类型 a 进行空判断,如果 a 包含一个值就进行解包,否则就返回一个默认值 b

let defaultColorName = "red"
var userDefinedColorName: String?  // nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse) // red

userDefinedColorName = "green"
colorNameToUse = userDefinedColorName ?? defaultColorName
print(colorNameToUse) // green

10 - 逻辑运算:逻辑运算符的操作对象是逻辑布尔值:逻辑非、逻辑与、逻辑或。注:&& 的优先级要比 || 高

print(false || true && false) // false
print(false && true || false) // false

nil

1 - Swift 的 nil 和 OC 中的 nil 并不一样:OC 中 nil 是一个指向不存在对象指针;Swift 中它是一个确定值,用来表示值缺失

var serverResponseCode: Int? = 404
serverResponseCode = nil // serverResponseCode 现在不包含值

// nil 不能用于非可选的常量和变量
let someValue = nil // 编译报错
// 代码中若有常量或者变量需要处理值缺失的情况
// 请把它们声明成对应的可选类型
let someThing: Int? = nil // 编译通过

断言 | 强制执行先决条件 | fatalError

1 - 断言和先决条件是在运行时所做的检查。使用全局的 assert 函数,接收一个 Bool 表达式和一个断言失败时显示的消息。注:断言会导致程序运行的中止,断言本身没有什么功能,只是方便程序员调试 bug,在发布的应用里最好不要使用

var m = 200
// 条件不成立就抛出错误信息,终止程序
assert(m >= 300, "m必须大于100") // 终止程序
assert(m >= 0)// 也可以省略错误信息,但不推荐,不利于调试

2 - 使用全局函数 precondition(_:_:file:line:) 来写一个先决条件。如果你使用 unchecked 模式编译代码,先决条件将不会进行检查,编译器会假设所有的先决条件总是为 true

let index = 0
// 条件为 false
precondition(index > -5, "Index must be greater than zero.")

:它和断言的使用方式几乎是一模一样,只是方法名不通罢了,那么区别在哪里 ?precondition 在 release 版本中依然奏效;Assert 只在开发版本中奏效

3 - fatalError(_:file:line:) 函数总是中断执行
fatalError("fuck") // 终止程序

 

posted on 2018-04-28 21:00  低头捡石頭  阅读(30)  评论(0编辑  收藏  举报

导航