概述阶段
1.swift中允许进行多次加包,但这也就意味着需要多次解包
2.解包顺序是从内向外,先解最内层的包
3.guard else语句相当于if语句中省略判断条件为真时大括号中的内容
4.guard let ... else也有解包的功能,但解包后的参数只能在条件判断中使用,而无法在后面的大括号中使用
代码阶段
可选值以及3种常规解包方式
//当你创建的变量有可能为nil的情况下,我们需要声明可选值
let str: String? = nil
//可选值解包方法1: 用 ?? 符号设定一个默认值
let length1 = str?.characters.count ?? 0
print(length1)
var length2:Int
//可选值解包方法2:用 if let语法解包
if let strTemp = str {
length2 = strTemp.characters.count
}else{
length2 = 0
}
print(length2)
//可选值解包方法3: 用 ! 符号强制解包,这个方法非必要,不要去用
let length = str!.characters.count
集合Set
//set的声明(声明Set必须指定类型)
var set0 = Set<Character>()
var set1: Set<String> = ["张三", "李四", "王五"]
//类型推断写法,一定要注明类型Set,不然系统会自动识别为Array
var set2: Set = ["张三", "李四", "王五"]
//随机删除一个元素,并不是真正删除第一个元素,因为set是无序的
set1.removeFirst()
//删除指定的某个元素
if let tempStr = set1.remove("张三"){
print(tempStr + "被删掉了")
}else{
print("就没发现张三")
}
//set的清空方式1
set1 = []
//set的清空方式2
set1.removeAll()
//set的插入
set1.insert("王二")
set1.insert("刘谋")
set1.insert("赵大")
//集合中元素个数
print(set1.count)
//是否为空,输出false
print(set1.isEmpty)
//set的查询
if set1.contains("王二") {
print("王二在集合中")
}
//set的遍历
for value in set1 {
print("集合中的元素:\(value)")
}
//set的排序遍历,正序
for value in set1.sorted(by: <) {
print("集合中的元素,已排序:\(value)")
}
Set和Array的相互转化
//初始化一个array
let array: [Int] = [1, 3, 5, 2]
//初始化一个set
var set = Set<Int>()
//array可以强转为set,由于set是无序的,所以转换后顺序随机
set = Set(array)
print(set)
//同样,set也可以强转为array
var array2 = [Int]()
array2 = Array(set)
print(array2)
//转换方法2:map函数,转为[int]
let array3 = set.map { $0 }
print(array3)
//转换方法3:flatMap,转为[String]
//注,只有flatMap函数可以使返回类型发生改变。如从Set<Int> -> [String]
let array4:[String] = set.flatMap { String($0) }
print(array4)
//转换方法4:sort函数
let array5 = set.sorted()
print(array5)
//转换方法5:filter函数
let array6 = set.filter {$0 > -1}
print(array6)
Set的最大值、最小值、交集、并集、补集、差集
let oneSet: Set = [1, 3, 5, 7, 9, 9]
let twoSet: Set = [0, 1, 2, 4, 6, 8]
let threeSet: Set = [2, 3, 5, 7]
let fourSet: Set = [3, 5, 7]
let fiveSet: Set = [11, 12, 13]
//最小值
print(oneSet.min()!)
//最大值
print(oneSet.max()!)
//并集(两个集合合并去重),输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(oneSet.union(twoSet).sorted())
// 交集(两个集合中共有的元素),输出:[1]
print(oneSet.intersection(twoSet).sorted())
//补集,(oneSet中有,而threeSet中没有的),输出:[1, 9]
print(oneSet.subtracting(threeSet).sorted())
//差集(两个集合中非共有的元素),输出:[1, 2, 9]
print(oneSet.symmetricDifference(threeSet).sorted())
//fourSet是否是oneSet的子集,输出:true
print(fourSet.isSubset(of: oneSet))
//oneSet是否是fourSet的父集,输出:true
print(oneSet.isSuperset(of: fourSet))
//fiveSet是否和oneSet没有交集,输出:true
print(fiveSet.isDisjoint(with: oneSet))
三目运算符、加包、解包、多次加解包
//Swift中依然是可以使用三目运算符的
let testInt = true ? 50 : 20
let a:Int? = 3
let b = 4
//?? 意为:若a不为nil,对a解包;若a为nil,使用b
let c1 = a ?? b
//如果用三目运算符,写法如下
let c2 = a != nil ? a! : b
//多次解包
let a1:Int??? = 3
//输出:Optional(Optional(Optional(3)))
print(a1)
//发生了解包,解掉了一层包,输出:Optional(Optional(3))
print(a1 ?? 4)
let a2:Int??? = nil
//输出:nil
print(a2)
let d = a2 ?? 4
//发生解包,用4来替代nil,输出:Optional(Optional(4))
print(d)
//再次解包,未发生默认值替代,输出:Optional(4)
print(d ?? 5)
//结论:
//1.可以进行多次加包,但加几次就需要解几次包
//2.解包顺序是从内向外,先解最内层的包
for循环中的范围操作符、元组遍历法
//swift与oc的for循环区别1:范围操作符...和..<
for index in 1..<5 {
print("\(index)")
}
//swift与oc的for循环区别2:元组遍历方式
let dict = ["spider": 8, "ant": 6, "cat": 4]
for (key, value) in dict {
print("\(key): \(value)")
}
while 和 repeat while
var n = 2
while n < 2 {
n = n * 2
}
print(n)
var m = 2
//repeat while 其实就相当于与do while语句,至少会执行一次
repeat {
m = m * 2
} while m < 2
print(m)
输出结果:2
输出结果:4
标签语句
var start:Int = 0
var final = 1000
//在Swift中,可以在其他循环和条件语句中嵌套循环和条件语句,以创建复杂的控制流结构。
//在标签语句中,可以使用带有break或continue语句的语句标签来结束或继续执行带标签的语句。
whileFunc: while start != final {
start += Int(arc4random_uniform(100)) // 随机增加一个数字
switch start {
case final: // 如果== 最终值结束循环
//注:这里如果光写break,会print最后一次,输出:1000
//但现在写的是break whileFunc,那么最后一次的break不会被执行,直接出方法
break whileFunc
case let x where x > final: //如果值大于1000 则初始化为0 继续开始循环
start = 0
//这里其实写不写无所谓,因为switch中穿透用的是fallthrough
//所以switch并不会识别continue关键字
continue whileFunc
default:
//这里指跳出switch循环
break
}
print(start)
}
//上述的写法等同于whileFunc2声明 + whileFunc2()
func whileFunc2() {
while start != final {
start += Int(arc4random_uniform(100)) // 随机增加一个数字
switch start {
case final: // 如果== 最终值结束循环
print("执行了这里" + String(start))
//由于whileFunc中是直接跳出方法而不是switch判断,所以这里用return
return
case let x where x > final: //如果值大于1000 则初始化为0 继续开始循环
start = 0
continue
default:
break
}
print(start)
}
}
//调用
whileFunc2()
var baseInt = 1
//当然,除了循环语句,条件语句也可以这么用
//虽然对条件语句而言,大部分情况下不需要这种用法
ifFunc:if baseInt > 0 {
for i in 0...100 {
baseInt += i
if baseInt > 20 {
break ifFunc
}
print(baseInt)
}
}
guard 语法
//现在要求当name为空或者等于张三的情况下,输出"无值通不过,张三通不过"
let name1: String? = "张三"
//解题方式1:用if语法来解
func checkName1(name:String?){
//注:第二个判断条件,首!是为了让bool值变为相反,尾!是为了强制解包
if name != nil && !(name?.contains("张三"))! {
}else{
print("无值通不过,张三通不过")
}
}
checkName1(name: nil)
checkName1(name: "张三")
//解题方式2:用guard else语法来解
func checkName2(name:String?){
//guard 后的条件语句内容与if是一致的
guard name != nil,!((name?.contains("张三"))!)else{
print("无值通不过,张三通不过")
//guard一定要带return
//所以guard一般用于方法内部需要对nil值做特殊判断的情况
return
//print("用了return,后面的代码就不会执行了")
}
}
checkName2(name: nil)
checkName2(name: "张三")
//解题方式3:用if let语法来解
func checkName3(name:String?){
//if let 语法实际上是做了个解包工作,方便参数的使用
//注意:这里故意使两个变量名一致,编译器会自动正确的识别他们
if let name = name,!(name.contains("张三")) {
}else{
print("无值通不过,张三通不过")
}
}
checkName3(name: nil)
checkName3(name: "张三")
//解题方式4:用guard let else语法来解
func checkName4(name:String?){
//guard let 语法实际上是做了个解包工作,方便参数的使用
//但guard let中,往往不能设置同名变量
guard let n = name,!(n.contains("张三")) else{
print("无值通不过,张三通不过")
return
}
}
checkName4(name: nil)
checkName4(name: "张三")
//解题方式5:用if语法,把判断条件内容反着写
func checkName5(name:String?){
//把判断条件内容全部反写,那么就可以不用else部分了
if name == nil || (name?.contains("张三"))! {
print("无值通不过,张三通不过")
}
}
checkName5(name: nil)
checkName5(name: "张三")
if语句中的元组类型
//如果元组类型出现在判断语句中,会按顺序对于元组类型的每一位上的元素进行判断
if (1, "zebra") < (2, "apple") { // 先判断第一个,在判断第二个
//结果为true
print("true")
}
String转Int类型
//大前提:Swift中Int转String是一定成功的,但String转Int有可能得到nil
let strValue1 = "18"
let strValue2 = "18.8"
if let n = Int(strValue1) {
//输出:转译成功:18
print("转译成功:\(n)")
}
if let n = Int(strValue2) {
print("转译成功:\(n)")
}else{
//输出:转译失败
print("转译失败")
}
//String转int方法1:利用double
if let dou:Double = Double(strValue2) {
let n:Int = Int(dou)
//注:Double转int不遵循四舍五入,直接抹去小数点后数字
print("转译成功1:\(n)")
}
//String转int方法2:用NSString的integerValue
//swift3中切分String字符串是比较繁琐的,所以如有必要推荐转为NSString进行切分转换
let myInt = (strValue2 as NSString).integerValue
print("转译成功3:\(myInt)")
//String转int方法3:按小数点切割
//注:Swift3中切割会相对繁琐一点,在Swift4中推出了str.prefix()就会简单很多
if(strValue2.contains(".")){
let range:Range = strValue2.range(of: ".")!
let frontStr = strValue2[strValue2.startIndex ..< range.lowerBound]
print("转译成功2:\(frontStr)")
}else{
if let n = Int(strValue2) {
print("转译成功2:\(n)")
}
}
String转Int的完整写法(还不完美)
/*
命题:
创建一个方法,接收一个String参数(不考虑空格)
如果其输入的满足数字规则数字,则输出四舍五入后的结果;
如果输入的不是数字,输出0
*/
func stringToInt(str:String) -> Int{
//判断输入值是否满足小数形式规则的方法
func isPurnFloat(string: String) -> Bool {
let scan: Scanner = Scanner(string: string)
var val:Float = 0
return scan.scanFloat(&val) && scan.isAtEnd
}
//先判断输入的string是否满足转换要求
guard isPurnFloat(string: str) else {
//不满足小数形式规则,直接输出0
return 0;
}
//判断string中是否包含小数点
if(str.contains(".")){
//按小数点分割
let range:Range = str.range(of: ".")!
let subStr1 = str[str.startIndex ..< range.lowerBound]
//先把前半部分转为int类型
var result:Int = Int(subStr1)!
//先取到整个小数部分
var subStr2 = str[range.upperBound ..< str.endIndex]
//再取到小数部分的第一位
subStr2 = subStr2[subStr2.startIndex..<subStr2.index(after: subStr2.startIndex)]
//然后判断其是否大于4
if let n = Int(subStr2) {
//大于4整数部分进1
if n > 4 {
result += 1
}
}
return result
}else{
//str中不包含小数点直接转整数输出
if let n = Int(str) {
return n
}
}
return 0
}
print(stringToInt(str: "以"))
print(stringToInt(str: "123"))
print(stringToInt(str: "123.5100"))