import UIKit
var str = "Hello, playground"
for c in "Hello world" {
print(c)
}
let names = ["zhangsan","lisi","wangwu","zhaoliu"]
for name in names {
print(name)
}
let numberOfLegs = ["spider":8,"ant":6,"cat":4]
for t in numberOfLegs {
print("(t.0) has (t.1) legs")
}
for (name, legs) in numberOfLegs {
print("(name) has (legs) legs")
}
//如何在Swift中进行循环控制
// for-in循环
//如果你不需要序列的每一个值,你可以使用下划线来取代遍历名以忽略值。
let base = 3
let power = 5
var answer = 1
for _ in 1...power {
answer *= base
}
print("(base) to the power of (power) is (answer)")
//for-in分段区间
//使用stride(from:to:by)函数来跳过不想要的标记(开区间)
//闭区间也同样适用,使用stride(from:through:by)即可。
let minuteInterval = 5
for tickMark in stride(from: 0, to: 50, by: minuteInterval) {
print(tickMark)
}
for tickMark in stride(from: 0, through: 50, by: minuteInterval) {
print(tickMark)
}
//while循环
//repeat-while循环(Objective-C do-while)
var count = 0
repeat {
print(count)
count += 1
} while count < 5
//更加强大的switch
//switch语句会将一个值与多个可能的模式匹配。然后基于第一个成功匹配的模式来执行合适的代码块。
//switch语句一定得是全面的。就是说,给定类型里每一个值都得被考虑到并且匹配到一个switch的case。如果无法提供一个switch case所有可能的值,你可以定义一个默认匹配所有的case来匹配所有未明确出来的值。这个匹配所有的情况用关键字default标记,并且必须在所有case的最后出现。
//Objective-C switch 语句如果不全面,仍然可以运行。
//char c = 'z';
//switch (c) {
//case 'a':
// NSLog(@"The first letter of the alphabet");
// break;
//case 'z':
// NSLog(@"The last letter of the alphabet");
// break;
//}
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
}
//没有隐式贯穿
//相比C和Objective-C里的switch语句来说,Swift里的switch语句不会默认从匹配case的末尾贯穿到下一个case里
//相反,整个switch语句会在匹配到第一个switch的case执行完毕之后推出,不再需要显式的break语句
//每一个case的函数体必须包含至少一个可执行的语句。
//在一个switch的case中匹配多个值可以用逗号分隔,并且可以写成多行
let anotherCharacter: Character = "a"
switch anotherCharacter {
//case "a":
case "A","a":
print("The letter A")
default:
print("Not the letter A")
}
//区间匹配
//switch 的case的值可以在一个区间中匹配
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
var naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are (naturalCount) (countedThings).")
//元组匹配
//你可以使用元组来在一个switch语句中测试多个值
//使用下划线()来表明匹配所有可能的值
let somePoint = (1,1)
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (, 0):
print("((somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, (somePoint.1) is on the y-axis)")
case [-2...2, -2...2]:
print("((somePoint.0), (somePoint.1)) is inside the box")
default:
print("((somePoint.0), (somePoint.1)) is outside of the box")
}
//值绑定
//switch的case可以将匹配到的值临时绑定为一个常量或者变量,来给case的函数体使用
//如果使用var关键字,临时的变量就会以合适的值来创建并初始化。对这个变量的任何改变都只会在case的函数体内有效
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of (x)")
case (0, let y)
print("on the x-axis with a y value of (y)")
case let (x, y)
print("somewhere else at ((x), (y))")
}
//where语句
//switch case可以使用where分句来检查是否符合特定的约束
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("((x), (y)) is on the line x == y")
case let (x, y) where x == -y:
print("((x), (y)) is on the line x == -y")
case let (x, y):
print("((x), (y)) is just some arbitrary point")
}
//复合匹配
//多种情形共享同一个函数体的多个情况可以在case后写多个模式来复合,在每个模式之间用逗号分隔。如果任何一个模式匹配了,那么这个情况都会被认为是匹配的。如果模式太长,可以把它们写成多行。
let someCharacter1: Character = "e"
switch someCharacter1 {
case "a", "e", "i", "o", "u":
print("(someCharacter1) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n",
"p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("(someCharacter1) is a consonant")
default:
print("(someCharacter1) is not a vowel or a consonant")
}
//复合匹配-值绑定
//复合匹配同样可以包含值绑定。所有复合匹配的模式都必须
//控制转移
//continue
//break
//fallthrough
//return
//throw
//continue 语句告诉循环停止正在做的事情并且再次从头开始循环的下一次遍历。它是说“我不再继续当前的循环遍历了”而不是离开整个的循环
//break语句会立即结束整个控制流语句。当你想要提前结束switch或者循环语句或者其他情况时可以在switch语句或者循环语句中使用break语句。
//当在循环语句中使用时,break会立即结束循环的执行,并且转移控制到循环结束花括号(})后的第一行代码上。当前遍历循环里的其他代码都不会被执行,并且余下的遍历循环也不会开始了。
//当在switch语句里使用时,break导致switch语句立即结束它的执行,并且转移控制到switch语句结束花括号(})之后的第一行代码上。
//fallthrough
//如果你确实需要C或者Objective-C风格的贯穿行为,你可以选择在switch每个case末尾使用fallthrough关键字。
let integerToDescribe = 5
var description = "The number (integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += "a prime number, and also"
fallthrough
default:
description += "an integer."
}
print(description)
//语句标签
//可以使用语句标签来给循环语句或者条件语句做标记。在一个条件语句中,你可以使用一个语句标签配合break语句来结束被标记的语句。在循环语句中,你可以使用语句标签来配合break或者continue语句来结束或者继续执行被标记的语句。
var number = 10
whileLoop : while number > 0 {
switch number {
case 9:
print("9")
case 10:
var sum = 0
for index in 0...10 {
sum += index
if index == 9 {
print(sum)
break whileLoop
}
}
default:
break
}
number -= 1
}
//guard
//guard语句,类似于if语句,基于布尔值表达式来执行语句。使用guard语句来要求一个条件必须是真才能执行guard之后的语句。与if语句不同,guard语句总是有一个else分句--else分句里的代码会在条件不为真的时候执行。
//https://github.com/objc-zen/objc-zen-book
//当编写条件语句的时候,左边的代码间距应该是一个“黄金”或者“快乐”的大道。这是说,不要嵌套if语句。多个return语句是OK的。这样可以避免圈复杂度(Cyclomatic Complexity),并且让代码更加容易阅读。因为你的方法的重要部分没有嵌套在分支上,你可以很清楚地找到相关的代码。
func isIPAddress(ipAddr: String) -> (Int, String) {
let components = ipAddr.split(separator: ".")
if components.count == 4 {
if let first = Int(components[0]), first >= 0 && first < 256 {
if let second = Int(components[1]), second >= 0 && second < 256 {
if let third = Int(components[2]), third >= 0 && third < 256 {
if let fourth = Int(components[3]), fourth >= 0 && fourth < 256 {
return (0, "")
} else {
return (4, "this forth components is wrong")
}
} else {
return (3, "this third components is wrong")
}
} else {
return (2, "this second components is wrong")
}
} else {
return (1, "this first components is wrong")
}
}
return (100, "ip 只能有四部分")
}
func isIPAddress2(ipAddr: String) -> (Int, String) {
let components = ipAddr.split(separator: ".")
guard components.count == 4 else {
return (100, "ip只能有四部分")
}
guard let first = Int(components[0]), first >= 0 && first < 256 else {
return (1, "第一个数不对")
}
guard let second = Int(components[1]), second >= 0 && second < 256 else {
return (2, "第二个数不对")
}
guard let third = Int(components[0]), third >= 0 && third < 256 else {
return (3, "第三个数不对")
}
guard let fourth = Int(components[0]), fourth >= 0 && fourth < 256 else {
return (4, "第四个数不对")
}
return (0, "")
}
//检查API的可用性
//Swift拥有内置的对API可用性的检查功能,它能够确保你你会悲剧地使用了对部署目标不可用的API。
//你可以在if或者guard语句中使用一个可用性条件来有条件地执行代码,基于在运行时你想用的哪个API是可用的。
if #available(iOS 10, *) {
}
//模式和模式匹配
//模式代表单个值或者复合值的结构
//模式分类
//通配符模式
//通配符模式由一个下划线(_)构成,用于匹配并忽略任何值。当你想忽略被匹配的值时可以使用该模式
for _ in 1...3 {
//...
}
//标识符模式
//标识符模式匹配任何值,并将匹配的值和一个变量或常量绑定起来
let someValue = 42
//值绑定模式
//值绑定模式把匹配到的值绑定给一个变量或常量。把匹配到的值绑定给常量时,用关键字let,绑定给变量时,用关键字var
let point = (3, 2)
switch point {
//将point中的元素绑定到 x 和 y
case let (x, y):
print("The point is at ((x), (y))")
}
//元组模式
//元组模式是由逗号分隔的,具有零个或多个模式的列表,并由一对圆括号括起来。元组模式匹配相应元组类型的值。
//你可以使用类型标注去限制一个元组模式能匹配那种元组类型。例如,在常量声明let(x, y):(Int, Int)=(1,2)中的元组模式(x,y):(Int, Int)只匹配两个元素都是Int类型的元组。
//当元组模式被用于for-in语句或者变量和常量声明时,它仅可以包含通配符模式、标识符模式、可选模式或者其他包含这些模式的元组模式。
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
//for (x, 0) in points {
//
//}
for (x, y) in points where y == 0 {
print("(x) and (y)")
}
//枚举用例模式
//枚举用例模式匹配现有的某个枚举类型的某个用例。枚举用例模式出现在switch语句中的case标签中,以及if、while、guard和for-in语句的case条件中。
//可选项模式
//可选项模式匹配Optional<Wrapped>枚举在some(Wrapped)中包装的值。
//可选项目模式为for-in语句提供了一种迭代数组的简便方式,只为数组中非nilde 元素执行循环体
let someOptional: Int? = 42
if case .some(let x) = someOptional {
print(x)
}
if case let x? = someOptional {
print(x)
}
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
for case let number? in arrayOfOptionalInts {
print("Found a (number)")
}
//类型转换模式
//有两种类型转换模式,is模式和as模式。is模式只出现在switch语句中的case标签中。
//is模式和as模式形式如下:
//is 类型
//模式 as 类型
//is模式仅当一个值的类型在运行时和is模式右边的指定类型一致,或者是其子类的情况下,才会匹配这个值。is模式和is运算符有相似表现,它们都进行类型转换,但是is模式没有返回类型。
//as模式仅当一个值的类型在运行时和as模式右边的指定类型一致,或者是其子类的情况下,才会匹配这个值。如果匹配成功,a被匹配的值的类型被转换成as模式右边指定的类型
protocol Animal {
var name: String { get }
}
struct Dog: Animal {
var name: String {
return "dog"
}
var runSpeed: Int
}
struct Bird: Animal {
var name: String {
return "bird"
}
var flightHeight: Int
}
struct Fish: Animal {
var name: String {
return "fish"
}
var depth: Int
}
let animals:[Any] = [Dog(runSpeed: 55), Bird(flightHeight: 1000), Fish(depth: 100)]
for animal in animals {
switch animal {
case let dog as Dog:
print("(dog.name) can run (dog.runSpeed)")
case let fish as Fish:
print("(fish.name) can dive depth (fish.depth)")
case is Bird:
print("bird can fly")
default:
print("unknown animal!")
}
}
//表达式模式
//表达式模式代表表达式的值。表达式模式只出现在switch语句中的case标签中
struct Employee {
var salary: Int
}
func ~= (left:ClosedRange<Int>, right:Employee) -> Bool {
return left.contains(right.salary)
}
var e:Employee = Employee(salary: 2000)
switch e {
case 0...1000:
print("吃不饱")
case 1000...5000:
print("勉强度日")
case 5000...10000:
print("还不错")
default:
print("高薪阶层")
}
网友评论