swift之方法(Methods)

最后更新于:2022-04-01 11:39:58

⽅法是与某些特定类型相关联的函数。 类、结构体、枚举都可以定义实例⽅法;实例⽅法为给定类型的实例封装了具体的任务与功能。 类、结构体、枚举也可以定义类型⽅法;类型⽅法与类型本⾝相关联。类型⽅法与 Objective-C 中的类⽅法(class methods)相似 结构体和枚举能够定义⽅法是 Swift 与 C/Objective-C 的主要区别之⼀ 1、实例方法: ~~~ import Foundation class Person { var age = 1; var name = "xiaoming"; //这就是实例方法,定义在所属类型的前后大括号之间 //实例⽅法能够隐式访问它所属类型的所有的其他实例⽅法和属性 func printAge() { print("the \(self) age is \(self.age)") } func printNameAndAge(){ print("the \(self) name is \(self.name)") self.printAge() } } let p1 = Person() p1.printNameAndAge() p1.name = "dzl" p1.age = 12; p1.printNameAndAge() //the _5_swift之_方法.Person name is xiaoming //the _5_swift之_方法.Person age is 1 //the _5_swift之_方法.Person name is dzl //the _5_swift之_方法.Person age is 12 ~~~ 类Person定义了两个属性,两个实例方法,其中实例方法printNameAndAge()调用实例方法printAge() (1)、方法的局部参数名称和外部参数名称 Swift 默认仅给⽅法的第⼀个参数名称⼀个局部参数名称;默认同时给第⼆个和后续的参数名称局部参数名称和外部参数名称 ~~~ class Cat { var name = "xiaohua" var age = 1 //这里newName只是局部参数名称,而newAge既是局部参数名称又是外部参数名称 func newNameAndAge(newName : String, newAge : Int) -> Void { self.name = newName self.age = newAge } //通过下划线(_)取消第二个及后续参数的默认外部参数名称 func useXiaHuaXian(newName : String, _ newAge : Int) { self.name = newName self.age = newAge } //自定义外部参数名称 func setNameAndAge(subNewName newName : String, subNewAge newAge : Int) { self.name = newName self.age = newAge } } var cat1 = Cat() cat1.newNameAndAge("cat1", newAge: 2) cat1.setNameAndAge(subNewName: "cat2", subNewAge: 3) cat1.useXiaHuaXian("cat3", 4) ~~~ (2)、在实例方法中修改值类型 结构体和枚举是值类型。⼀般情况下,值类型的属性不能在它的实例⽅法中被修改。但是,如果你确实需要在某个具体的⽅法中修改结构体或者枚举的属性,你可以选择 变异⽅法(mutating)  这个⽅法,然后⽅法就可以从⽅法内部改变它的属性;并且它做的任何改变在⽅法结束时还会保留在原始结构中。⽅法还可以给它隐含的 self  属性赋值⼀个全新的实例,这个新实例在⽅法结束后将替换原来的实例 ~~~ struct MyPoint { var x = 0.0 var y = 0.0 mutating func changePoint(newX newX : Double, newY : Double) { x += newX y += newY } //⽅法还可以给它隐含的 self 属性赋值⼀个全新的实例,这个新实例在⽅法结束后将替换原来的实例 mutating func changeMyPoint(newX : Double, newY : Double) { self = MyPoint(x: x + newX, y: y + newY) } } var point1 = MyPoint(x: 2, y: 3) point1.changePoint(newX: 1, newY: 1); print("the point, x = \(point1.x) y = \(point1.y)") point1.changeMyPoint(2, newY: 2) print("the point, x = \(point1.x) y = \(point1.y)") //the point, x = 3.0 y = 4.0 //the point, x = 5.0 y = 6.0 ~~~ 2、类型方法(加关键字static) ~~~ enum EnumTypeFunc : Int{ case enum1 = 1 case enum2, enum3 static func getEnum2() -> EnumTypeFunc { return enum2 } } struct StructTypeFunc { static var name = "struct" static func getName() -> String { return name } } class ClassTypeFunc { static var name = "class" static func getName1() -> String { return name } //关键字class允许子类重写父类方法 class func getName2() -> String { return name } } print(EnumTypeFunc.getEnum2()) print(StructTypeFunc.getName()) print(ClassTypeFunc.getName1()) print(ClassTypeFunc.getName2()) //enum2 //struct //class //class ~~~
';

swift之属性

最后更新于:2022-04-01 11:39:56

属性将值跟特定的类、结构或枚举关联。存储属性存储常量或变量作为实例的⼀部分,⽽计算属性计算(不是存储)⼀个值。计算属性可以⽤于类、结构体和枚举,存储属性只能⽤于类和结构体 存储属性和计算属性通常与特定类型的实例关联。但是,属性也可以直接作⽤于类型本⾝,这种属性称为类型属性 另外,还可以定义属性观察器来监控属性值的变化,以此来触发⼀个⾃定义的操作。属性观察器可以添加到⾃⼰定义的存储属性上,也可以添加到从⽗类继承的属性上。 ## 一、存储属性 存储属性,就是类或结构体的成员变量或者常量 ~~~ struct Phone { var price : Float let brand : String //这两个都是存储属性,一个是常量一个是变量 } var phone1 = Phone(price: 999, brand: "xiaomi1") let phone2 = Phone(price: 1799, brand: "xiaomiNote") //phone1是变量结构体实例 //phone2是常量结构体实例 phone1.price = 888 //brand 是常量属性,无论结构体实例是变量实例还是常量实例,brand都不可变 //由于phone2是常量实例,所以它的属性,无论是变量还是常量,都不可变 ~~~ 如果结构体换成类呢: ~~~ class Phone1 { var price : Float let brand : String init () { price = 10.0 brand = "xiaomi" } } var phone3 = Phone1() let phone4 = Phone1() print("\(phone3.price), \(phone3.brand)") //10.0, xiaomi phone4.price = 100 //phone4.brand = "red mi" //不能改 //不是说phone4是常量实例吗,属性值怎么可以改? //其实说白了还是值类型和引用类型的区别,类是引用类型,phone4定义为常量是不能修改,即不能 phone4 = phone3 这样是不可以的,但是let对类的属性并不影响 ~~~ 延迟存储属性: 延迟存储属性是指当第⼀次被调⽤的时候才会计算其初始值的属性。在属性声明前使⽤ lazy  来标⽰⼀个延迟存储属性。 注意: 必须将延迟存储属性声明成变量(使⽤ var  关键字),因为属性的初始值可能在实例构造完成之后才会得到。⽽常量属性在构造过程完成之前必须要有初始值,因此常量⽆法声明成延迟属性。 ~~~ func complexCompute() -> Int { //这里假设10是经过大量复杂计算所得到的结果 return 10 } class MathCompute { lazy var computeResult = complexCompute() var x = 10 } //这里创建MathCompute对象后如果不访问computeResult属性,就不会调用复杂函数去计算属性值,只有在第一次访问computeResult的时候才去计算初始值,其它属性则是在创建对象的时候就计算初始值 ~~~ ## 二、计算属性 计算属性不直接存储值,⽽是提供⼀个 getter 和⼀个可选的 setter,来间接获取和设置其他属性或变量的值 ~~~ struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct Rect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } } var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0)) let initialSquareCenter = square.center //此时会调用get square.center = Point(x: 15.0, y: 15.0) //此时会调用set print("square.origin is now at (\(square.origin.x), \(square.origin.y))") //"square.origin is now at (10.0, 10.0)” ~~~ 便捷 setter 声明 如果计算属性的 setter 没有定义表⽰新值的参数名,则可以使⽤默认名称 newValue  。下⾯是使⽤了便捷 setter 声明的 Rect  结构体代码: ~~~ struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } } ~~~ 另外还有只读计算属性,只有getter没有setter。只读计算属性也可以去掉get和{}。 ## 三、属性观察器 属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调⽤属性观察器,甚⾄新的值和现在的值相同的时候也不例外。 可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的⽅式为继承的属性(包括存储属性和计算属性)添加属性观察器。 注意: 不需要为⾮重载的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。 可以为属性添加如下的⼀个或全部观察器: willSet  在新的值被设置之前调⽤ didSet  在新的值被设置之后⽴即调⽤ willSet  观察器会将新的属性值作为常量参数传⼊,在 willSet  的实现代码中可以为这个参数指定⼀个名称,如果不指定则参数仍然可⽤,这时使⽤默认名称 newValue  表⽰。 类似地, didSet  观察器会将旧的属性值作为参数传⼊,可以为该参数命名或者使⽤默认参数名 oldValue  。 注意: ⽗类的属性在⼦类的构造器中被赋值时,它在⽗类中的 willSet  和 didSet  观察器会被调⽤。 ~~~ class Dog { var dogName : String = "littledog" { willSet(newDogName) { //设置之前调用 print("old dog name is \(dogName) ,and the new dog name is \(newDogName)") } didSet { //设置之后调用 print("new dog name is \(dogName)") } } } var dog1 = Dog() dog1.dogName = "bigDog" //old dog name is littledog ,and the new dog name is bigDog //new dog name is bigDog class LittleDog: Dog { override init() { super.init() self.dogName = "---this is little dog---" } } var littleDog1 = LittleDog() //⽗类的属性在⼦类的构造器中被赋值时,它在⽗类中的 willSet 和 didSet 观察器会被调⽤。 //old dog name is littledog ,and the new dog name is ---this is little dog--- //new dog name is ---this is little dog--- ~~~ 注意: 如果在⼀个属性的 didSet  观察器⾥为它赋值,这个值会替换该观察器之前设置的值。 ## 四、全局变量和局部变量 计算属性和属性观察器所描述的模式也可以⽤于全局变量和局部变量。 全局变量是在函数、⽅法、闭包或任何类型之外定义的变量。局部变量是在函数、⽅法或闭包内部定义的变量。 另外,在全局或局部范围都可以定义计算型变量和为存储型变量定义观察器。计算型变量跟计算属性⼀样,返回⼀个计算的值⽽不是存储值,声明格式也完全⼀样。 注意: 全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地⽅在于,全局的常量或变量不需要标记 lazy  特性。 局部范围的常量或变量不会延迟计算。 ## 五、类型属性 实例的属性属于⼀个特定类型实例,每次类型实例化后都拥有⾃⼰的⼀套属性值,实例之间的属性相互独⽴。 还可以为类型本⾝定义属性,不管类型有多少个实例,这些属性都只有唯⼀⼀份。这种属性就是类型属性。 值类型的存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算属性⼀样只能定义成变量属性。 注意: 跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本⾝⽆法在初始化过程中使⽤构造器给类型属性赋值。 类型属性语法: ~~~ struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 1 } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 6 } } class SomeClass { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 27 } class var overrideableComputedTypeProperty: Int { return 107 } } //关键字 class 来⽀持⼦类对⽗类的实现进⾏重写 class SubSomeClass: SomeClass { override class var overrideableComputedTypeProperty: Int { return 1077 } } print(SomeClass.storedTypeProperty) print(SomeClass.computedTypeProperty) print(SomeClass.overrideableComputedTypeProperty) print(SubSomeClass.overrideableComputedTypeProperty) //Some value. //27 //107 //1077 ~~~
';

swift之类和结构体

最后更新于:2022-04-01 11:39:54

类和结构体是⼈们构建代码所⽤的⼀种通⽤且灵活的构造体。我们可以使⽤完全相同的语法规则来为类和结构体定义属性(常量、变量)和添加⽅法,从⽽扩展类和结构体的功能。 与其他编程语⾔所不同的是,Swift 并不要求你为⾃定义类和结构去创建独⽴的接⼝和实现⽂件。你所要做的是在⼀个单⼀⽂件中定义⼀个类或者结构体,系统将会⾃动⽣成⾯向其它代码的外部接⼝。 ## 一、类和结构体的对比 1、Swift 中类和结构体有很多共同点。共同处在于: (1)定义属性⽤于存储值 (2)定义⽅法⽤于提供功能 (3)定义附属脚本⽤于访问值 (4)定义构造器⽤于⽣成初始化值 (5)通过扩展以增加默认实现的功能 (6)实现协议以提供某种标准功能 与结构体相⽐,类还有如下的附加功能: (1)继承允许⼀个类继承另⼀个类的特征 (2)类型转换允许在运⾏时检查和解释⼀个类实例的类型 (3)解构器允许⼀个类实例释放任何其所被分配的资源 (4)引⽤计数允许对⼀个类的多次引⽤ 注意: 结构体总是通过被复制的⽅式在代码中传递,因此请不要使⽤引⽤计数。 2、定义: 类使用关键字class,结构体使用关键字struct ~~~ class SomeClass { // class definition goes here } struct SomeStructure { // structure definition goes here } ~~~ 注意: 在你每次定义⼀个新类或者结构体的时候,实际上你是有效地定义了⼀个新的 Swift 类型。因此请使⽤  UpperCamelCase  这种⽅式来命名(如  SomeClass和 SomeStructure  等),以便符合标准Swift 类型的⼤写命名⻛格(如 String  , Int  和 Bool  )。相反的,请使⽤ lowerCamelCase  这种⽅式为属性和⽅法命名(如 framerate  和 incrementCount  ),以便和类区分。 这是官方建议,但如果你非要用小写,属性和方法非要用大写,那也不会出错 下面定义一个类和一个结构体: ~~~ class PersonClass { var name : String = "" var age : Int = 0 var sex : String? } struct Dog { var master = PersonClass() var dogName = "" } ~~~ 除了关键字不一样,看不出什么区别的 3、类和结构体实例(通常类的实例叫做类对象) 类PersonClass是描述一类人的共同属性,并没有具体到哪个人,所以需要一个实例来具体描述某一个人,结构体也是一样,下面是生成实例的语法: ~~~ class PersonClass { var name : String = "" var age : Int = 0 var sex : String? } struct Dog { var master = PersonClass() var dogName = "" } let onePerson = PersonClass() let oneDog = Dog() ~~~ 4、属性访问: 通过使⽤点语法(dot syntax),可以访问实例中所含有的属性。其语法规则是,实例名后⾯紧跟属性名,两者通过点号(.)连接 ~~~ struct Mouse { var brand = "apple" var price = 999.0 } class Computer { var mouse = Mouse() var display = "dell" var keyboard = "lenovo" var mainframe = "asus" var price = 9999.0 } var oneMouse = Mouse() var oneComputer = Computer() print("the mouse brand is \(oneMouse.brand), the computer display is \(oneComputer.display)") print("the mouse's price of the computer is \(oneComputer.mouse.price)") oneComputer.mouse.price = 888.0 print("the mouse's price of the computer is \(oneComputer.mouse.price)") //注意: 与 Objective-C 语⾔不同的是,Swift 允许直接设置结构体属性的⼦属性。 //上⾯的最后⼀个例⼦,就是直接设置了 oneComputer 中 oneMouse 属性的 price 这个 //⼦属性,以上操作并不需要重新设置 oneMouse 属性。 //the mouse brand is apple, the computer display is dell //the mouse's price of the computer is 999.0 //the mouse's price of the computer is 888.0 ~~~ 5、结构体类型的成员逐⼀构造器 所有结构体都有⼀个⾃动⽣成的成员逐⼀构造器,⽤于初始化新结构体实例中成员的属性。新实例中各个属性的初始值可以通过属性的名称传递到成员逐⼀构造器之中: ~~~ var twoMouse = Mouse(brand: "lenovo", price: 500.0) print("the mouse's brand is \(twoMouse.brand), and the price is \(twoMouse.price)") //the mouse's brand is lenovo, and the price is 500.0 ~~~ 与结构体不同,类实例没有默认的成员逐⼀构造器 ## 二、结构体和枚举是值类型 值类型被赋予给⼀个变量、常量或者本⾝被传递给⼀个函数的时候,实际上操作的是其值的拷⻉ 在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且都是以结构体的形式在后台所实现 在 Swift 中,所有的结构体和枚举类型都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制 ~~~ var twoMouse = Mouse(brand: "lenovo", price: 500.0) print("the mouse's brand is \(twoMouse.brand), and the price is \(twoMouse.price)") //the mouse's brand is lenovo, and the price is 500.0 var threeMouse = twoMouse threeMouse.price = 555.0 print("twoMouse price is \(twoMouse.price)") print("threeMouse price is \(threeMouse.price)") //twoMouse price is 500.0 //threeMouse price is 555.0 ~~~ 上面例子中,将twoMouse赋给threeMouse,其实就是讲twoMouse拷贝一份给threeMouse,修改threeMouse中的值,twoMouse中的值并不受影响 ## 三、类是引用类型 ~~~ var computer1 = Computer() print("the computer1's price is \(computer1.price)") var computer2 = computer1 computer2.price = 1000000.0 print("the computer2's price is \(computer2.price)") print("the computer1's price is \(computer1.price)") //the computer1's price is 9999.0 //the computer2's price is 1000000.0 //the computer1's price is 1000000.0 ~~~ 与值类型不同,引⽤类型在被赋予到⼀个变量、常量或者被传递到⼀个函数时,操作的是引⽤,其并不是拷⻉。因此,引⽤的是已存在的实例本⾝⽽不是其拷⻉,所以上面操作computer2的price属性时,computer1的price属性值也改变了,其实computer1和computer2指向同一个对象,它们操纵的也是同一个对象,这就是引用 值类型和引用类型分析如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b1a034d5df.jpg) 1、恒等运算符 因为类是引⽤类型,有可能有多个常量和变量在后台同时引⽤某⼀个类实例。(对于结构体和枚举来说,这并不成⽴。因为它们作为值类型,在被赋予到常量、变量或者传递到函数时,其值总是会被拷⻉。) 如果能够判定两个常量或者变量是否引⽤同⼀个类实例将会很有帮助。为了达到这个目的,Swift 内建了两个恒等运算符: 等价于 ( === ) 不等价于 ( !== ) 请注意 “等价于"  (⽤三个等号表⽰,===) 与 “等于"  (⽤两个等号表⽰,==)的不同:    “等价于”表⽰两个类类型(class type)的常量或者变量引⽤同⼀个类实例。    “等于”表⽰两个实例的值“相等”或“相同”,判定时要遵照类设计者定义定义的评判标准,因此相⽐于“相等”,这是⼀种更加合适的叫法。 ~~~ if computer1 === computer2 { print("computer1 等价于 computer2") } else { print("computer1 不等价于 computer2") } //computer1 等价于 computer2 ~~~ 2、指针 在 C,C++ 或者 Objective-C 语⾔中,使⽤指针来引⽤内存中的地址。⼀个 Swift 常量或者变量引⽤⼀个引⽤类型的实例与 C 语⾔中的指针类似,不同的是并不直接指向内存中的某个地址,⽽且也不要求你使⽤星号(*)来表明你在创建⼀个引⽤。Swift 中这些引⽤与其它的常量或变量的定义⽅式相同。 四、类和结构体的选择 什么时候使用类,什么时候使用结构体呢? 按照通⽤的准则,当符合⼀条或多条以下条件时,请考虑构建结构体: 结构体的主要⺫的是⽤来封装少量相关简单数据值。 有理由预计⼀个结构体实例在赋值或传递时,封装的数据将会被拷⻉⽽不是被引⽤。 任何在结构体中储存的值类型属性,也将会被拷⻉,⽽不是被引⽤。 结构体不需要去继承另⼀个已存在类型的属性或者⾏为 五、字符串(String)、数组(Array)、和字典(Dictionary)类型的赋值与复制 Swift 中 字符串(String)  , 数组(Array)  和 字典(Dictionary)  类型均以结构体的形式实现。这意味着String,Array,Dictionary类型数据被赋值给新的常量或变量,或者被传⼊函数或⽅法中时,它们的值会发⽣拷⻉⾏为(值传递⽅式) Objective-C中 字符串(NSString)  , 数组(NSArray)  和 字典(NSDictionary)  类型均以类的形式实现,这与Swfit中以值传递⽅式是不同的。NSString,NSArray,NSDictionary在发⽣赋值或者传⼊函数(或⽅法)时,不会发⽣值拷⻉,⽽是传递已存在实例的引⽤ 其实说白了,只要理解了什么是值类型,什么是引用类型,上面这些都很好理解。
';

swift之枚举

最后更新于:2022-04-01 11:39:51

在C语言中枚举名和一个整型值相对应 Swift中的枚举更加灵活,不必给每⼀个枚举成员提供⼀个值。如果给枚举成员提供⼀个值(称为“原始”值),则该值的类型可以是字符串,字符,或是⼀个整型值或浮点数。 此外,枚举成员可以指定任何类型的相关值存储到枚举成员值中,就像其他语⾔中的联合体(unions)和变体(variants)。你可以定义⼀组通⽤的相关成员作为枚举的⼀部分,每⼀组都有不同的⼀组与它相关的适当类型的数值。 1、枚举语法 使⽤ enum  关键词来创建枚举并且把它们的整个定义放在⼀对⼤括号内: ~~~ enum SomeEnumeration { // enumeration definition goes here } ~~~ ~~~ enum CompassPoint { case North case South case East case West } // North,South,East 和 West 不会隐式地赋值为了 0 , 1 , 2 和 3 print(CompassPoint.North) //North //多个成员值可以在同一行上,用逗号隔开 enum T1 { case T11, T12, T13, T14 } print("\(T1.T11), \(T1.T12)") //T11, T12 //每个枚举定义了一个全新的类型,他们的名字必须以大写字母开头 var t2 = T1.T12 //t2的类型可以被推断出来 let t1 : T1 = .T13 //定义一个变量或常量为枚举类型的时候,如果指定了变量的枚举类型,可以使用如上所示的缩写语法 t2 = .T13 //当t2的类型已知的时候,也可以省略枚举名 ~~~ 2、匹配枚举值和switch语句 ~~~ enum Test1 { case TestValue1, TestValue2, TestValue3, TestValue4 } let test : Test1 = .TestValue2 switch test { case .TestValue1: print("\(Test1.TestValue1)") case .TestValue2: print("\(Test1.TestValue2)") case .TestValue3: print("\(Test1.TestValue3)") case .TestValue4: print("\(Test1.TestValue4)") } //switch语句必须穷举所有的枚举值,否则不能通过编译,或者提供一个default分支,此时可以不穷举所有枚举值 //TestValue2 ~~~ 3、相关值 可以定义 Swift 的枚举存储任何类型的相关值,如果需要的话,每个成员的数据类型可以是各不相同的。枚举的这种特性跟其他语⾔中的可辨识联合(discriminated unions),标签联合(tagged unions),或者变体(variants)相似 ~~~ enum MyPhone { case Describe1(String, Int) case Describe2(String) } var phone1 = MyPhone.Describe1("小米", 1) switch phone1 { case MyPhone.Describe1(let param1, let param2) : print("\(param1), \(param2)") case MyPhone.Describe2(let param3): print(param3) } phone1 = .Describe2("小米1") switch phone1 { case MyPhone.Describe1(let param1, let param2) : print("\(param1), \(param2)") case MyPhone.Describe2(let param3): print(param3) } //小米, 1 //小米1 ~~~ 4、原始值 作为相关值的另⼀种选择,枚举成员可以被默认值(称为原始值)赋值,其中这些原始值具有相同的类型。 原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯⼀的。 注意: 原始值和相关值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值。对于⼀个特定的枚举成员,它的原始值始终是相同的。 相关值是当你在创建⼀个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。 ~~~ enum OriginalValue : Int { case Age1 = 10 case Age2 = 20 case Age3 = 30 } print(OriginalValue.Age2.rawValue) //20 ~~~ (1)原始值的隐式赋值 ~~~ enum OriginalValue : Int { case Age1 = 10 case Age2 //第一个赋值为10,后面的将隐式赋值,隐式赋值的值依次递增1 case Age3 } print(OriginalValue.Age2.rawValue) //11 enum OriginalValue1 : Int { case Value1 //如果第一个没有被赋值,自动赋值为0 case Value2 = 3 case Value3 } print(OriginalValue1.Value1.rawValue) print(OriginalValue1.Value2.rawValue) print(OriginalValue1.Value3.rawValue) //0 //3 //4 ~~~ (2)使⽤原始值初始化枚举变量 如果在定义枚举类型的时候使⽤了原始值,那么将会⾃动获得⼀个初始化⽅法,这个⽅法将原始值类型作为参数,返回枚举成员或者 nil  。你可以使⽤这种初始化⽅法来创建⼀个新的枚举变量。 ~~~ enum ScoreLevel : Int { case Level1 = 1, Level2, Level3, Level4, Level5 } let scoreLevel = ScoreLevel(rawValue: 3) //返回值是可选类型 print(scoreLevel!) //Level3 ~~~ 5、递归枚举 算数表达式的⼀个重要特性是,表达式可以嵌套使⽤。例如,表达式 (5 + 4) * 2  乘号右边是⼀个数字,左边则是另⼀个表达式。因为数据是嵌套的,因⽽⽤来存储数据的枚举类型也许要⽀持这种嵌套————这表⽰枚举类型需要⽀持递归。 递归枚举(recursive enumeration)是⼀种枚举类型,表⽰它的枚举中,有⼀个或多个枚举成员拥有该枚举的其他成员作为相关值。使⽤递归枚举时,编译器会插⼊⼀个中间层。你可以在枚举成员前加上 indirect  来表⽰这成员可递归。 ~~~ enum ArithmeticExpression { case Number(Int) indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) } //也可以在枚举类型开头加上 indirect 关键字来表⽰它的所有成员都是可递归的 indirect enum ArithmeticExpression1 { case Number(Int) //有⼀个或多个枚举成员拥有该枚举的其他成员作为相关值 case Addition(ArithmeticExpression1, ArithmeticExpression1) case Multiplication(ArithmeticExpression1, ArithmeticExpression1) } func evaluate(expression: ArithmeticExpression) -> Int { switch expression { case .Number(let value): return value case .Addition(let left, let right): return evaluate(left) + evaluate(right) //至于这里面怎么操作自己决定 case .Multiplication(let left, let right): return evaluate(left) * evaluate(right) } } // 计算 (5 + 4) * 2 let five = ArithmeticExpression.Number(5) let four = ArithmeticExpression.Number(4) let sum = ArithmeticExpression.Addition(five, four) //计算两个数相加 print(evaluate(sum)) //这里执行evalute函数,进去后匹配到.Addition分支,分支中left又是.Number类型,返回数值进行计算 let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2)) print(evaluate(product)) //9 //18 ~~~
';

swift之闭包(closure)

最后更新于:2022-04-01 11:39:49

闭包是⾃包含的函数代码块,可以在代码中被传递和使⽤。 Swift 中的闭包与 C 和Objective-C 中的代码块(blocks)以及其他⼀些编程语⾔中的 lambdas 函数⽐较相似。 闭包可以捕获和存储其所在上下⽂中任意常量和变量的引⽤。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift 会为您管理在捕获过程中涉及到的所有内存操作。 在函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之⼀: 全局函数是⼀个有名字但不会捕获任何值的闭包 嵌套函数是⼀个有名字并可以捕获其封闭函数域内值的闭包 闭包表达式是⼀个利⽤轻量级语法所写的可以捕获其上下⽂中变量或常量值的匿名闭包 Swift 的闭包表达式拥有简洁的⻛格,并⿎励在常⻅场景中进⾏语法优化,主要优化如下: 利⽤上下⽂推断参数和返回值类型 隐式返回单表达式闭包,即单表达式闭包可以省略 return  关键字 参数名称缩写 尾随(Trailing)闭包语法 1、闭包表达式 (1)先看一下自带的sort函数 Swift 标准库提供了名为 sort  的函数,会根据您提供的⽤于排序的闭包函数将已知类型数组中的值进⾏排序。 ⼀旦排序完成, sort(_:)  ⽅法会返回⼀个与原数组⼤⼩相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sort(_:)  ⽅法修改。 ~~~ let strs = ["ashdif", "gsdfao", "dsdokfn", "csddf"] func compare(str1 : String, str2 : String) -> Bool { return str1 > str2 } var newStrs = strs.sort(compare) print(strs) print(newStrs) //["ashdif", "gsdfao", "dsdokfn", "csddf"] //["gsdfao", "dsdokfn", "csddf", "ashdif"] ~~~ (2)闭包表达式语法 闭包表达式语法有如下⼀般形式: ~~~ { (parameters) -> returnType in statements } ~~~ 闭包表达式语法可以使⽤常量、变量和 inout  类型作为参数,不提供默认值。 也可以在参数列表的最后使⽤可变参数。 元组也可以作为参数和返回值。 ~~~ let strs = ["ashdif", "gsdfao", "dsdokfn", "csddf"] func compare(str1 : String, str2 : String) -> Bool { return str1 > str2 } var newStrs = strs.sort(compare) print(strs) print(newStrs) var newStrs1 = strs.sort({(str1 : String, str2 : String) -> Bool in return str1 < str2 }) print(newStrs1) //["ashdif", "gsdfao", "dsdokfn", "csddf"] //["gsdfao", "dsdokfn", "csddf", "ashdif"] //["ashdif", "csddf", "dsdokfn", "gsdfao"] ~~~ (3)根据上下文推断类型 ~~~ let strs = ["ashdif", "gsdfao", "dsdokfn", "csddf"] func compare(str1 : String, str2 : String) -> Bool { return str1 > str2 } var newStrs = strs.sort(compare) print(strs) print(newStrs) var newStrs1 = strs.sort({(str1 : String, str2 : String) -> Bool in return str1 < str2 }) print(newStrs1) var newStrs2 = strs.sort({str1, str2 in return str1 > str2}) print(newStrs2) //["ashdif", "gsdfao", "dsdokfn", "csddf"] //["gsdfao", "dsdokfn", "csddf", "ashdif"] //["ashdif", "csddf", "dsdokfn", "gsdfao"] //["gsdfao", "dsdokfn", "csddf", "ashdif"] ~~~ (4)单表达式闭包隐式返回 单⾏表达式闭包可以通过隐藏 return  关键字来隐式返回单⾏表达式的结果 ~~~ var newStrs2 = strs.sort({str1, str2 in str1 > str2}) ~~~ (5)参数名称缩写 Swift ⾃动为内联函数提供了参数名称缩写功能,您可以直接通过 $0  , $1  , $2  来顺序调⽤闭包的参数。 如果您在闭包表达式中使⽤参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进⾏推断。  in  关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成: ~~~ var newStrs2 = strs.sort({ $0 > $1}) ~~~ (6)运算符函数 实际上还有⼀种更简短的⽅式来撰写上⾯例⼦中的闭包表达式。 Swift 的 String  类型定义了关于⼤于号 ( >  ) 的字符串实现,其作为⼀个函数接受两个 String  类型的参数并返回 Bool  类型的值。 ~~~ var newStrs2 = strs.sort(>) ~~~ 2、尾随闭包 如果您需要将⼀个很⻓的闭包表达式作为最后⼀个参数传递给函数,可以使⽤尾随闭包来增强函数的可读性。 尾随闭包是⼀个书写在函数括号之后的闭包表达式,函数⽀持将其作为最后⼀个参数调⽤。 ~~~ var newStrs3 = strs.sort() {$0 > $1} ~~~ ~~~ let hanzi = [0 : "零", 1 : "壹", 2 : "贰", 3 : "叁", 4 : "肆", 5 : "伍", 6 : "陆", 7 : "柒", 8 : "捌", 9 : "玖"] let numbers = [23342, 832, 976] let numbersHZ = numbers.map() { (var number) -> String in var outHZ = "" while number > 0 { outHZ = hanzi[number % 10]! + outHZ number /= 10 } return outHZ } print(numbers) print(numbersHZ) //[23342, 832, 976] //["贰叁叁肆贰", "捌叁贰", "玖柒陆"] ~~~ 再来一个简单的例子: ~~~ func trailingClosure(a : Int, b : Int, c : (Int, Int) -> Bool) -> Int{ if c(a, b) { return a }else { return b } } let result = trailingClosure(10, b: 13) {//我的理解,简单来说就是写在括号外面,看着好看 $0 > $1 } print(result) //13 ~~~ 3、捕获值 闭包可以在其定义的上下⽂中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引⽤和修改这些值。 Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。 嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。 ~~~ //求一个数x的y次方 func makecalculate(x : Int, y : Int) -> () -> Int { var ret = 1 func achieve() -> Int { for var i = 0; i < y; i++ { //捕获参数y ret *= x //捕获变量ret和参数y } return ret } return achieve } let achiveFunc = makecalculate(3, y: 4) print(achiveFunc()) //81 ~~~ achieve函数并没有任何参数,但是在函数体内访问了 ret 和 x , y 变量。这是因为其通过捕获在包含它的函数体内已经存在的 ret 和 x , y 变量的引⽤(reference)⽽实现。捕捉了变量引⽤,保证了 ret 和 x, y 变量在调⽤完 makecalculate  后不会消失,并且保证了在下⼀次执⾏ achieve 函数时, ret 可以继续增加。 4、闭包是引用类型 ⽆论您将函数/闭包赋值给⼀个常量还是变量,您实际上都是将常量/变量的值设置为对应函数/闭包的引⽤
';

swift之函数(functions)

最后更新于:2022-04-01 11:39:47

函数是用来完成特定任务的独立代码块 Swift 统⼀的函数语法⾜够灵活,可以⽤来表⽰任何函数,包括从最简单的没有参数名字的 C ⻛格函数,到复杂的带局部和外部参数名的 Objective-C ⻛格函数。参数可以提供默 认值,以简化函数调⽤。参数也可以既当做传⼊参数,也当做传出参数,也就是说,⼀旦函数执⾏结束,传⼊的参数值可以被修改。 在 Swift 中,每个函数都有⼀种类型,包括函数的参数值类型和返回值类型。你可以把函数类型当做任何其他普通变量类型⼀样处理,这样就可以更简单地把函数当做别的函数的 参数,也可以从其他函数中返回函数。函数的定义可以写在在其他函数定义中,这样可以在嵌套函数范围内实现功能封装。 1、函数的定义与调用 定义一个函数时,可以定义⼀个或多个有名字和类型的值,作为函数的输⼊(称为参数,parameters),也可以定义某种类型的值作为函数执⾏结束的输出(称为返回类型)。 每个函数有个函数名,⽤来描述函数执⾏的任务。要使⽤⼀个函数时,你⽤函数名“调⽤”,并传给它匹配的输⼊值(称作实参,arguments)。⼀个函数的实参必须与函数参数表⾥参数的顺序⼀致。 ~~~ //myAge myName就是参数标签,可有可无,写出来可以清楚的知道参数的意思,跟oc中一样 //参数1 age 类型Int,参数2 name 类型String,返回值类型 String func callFunc(myAge age : Int, myName name : String) -> String { return "name:" + name + ",age:" + String(age) } print(callFunc(myAge: 25, myName: "dzl"))//这里直接输出函数返回值 //name:dzl,age:25 //Program ended with exit code: 0 ~~~ 2、函数参数与返回值 函数参数与返回值在Swift中极为灵活。你可以定义任何类型的函数,包括从不带参数的简单函数到复杂的带有表达性参数名和不同参数选项的复杂函数。 (1)无参函数 ~~~ //下面这两种形式都是无参,无返回值的函数,当没有返回值时,可以指定返回值类型为Void,也可以省略不写 func noParameter() -> Void { print("no parametr, no return value") } func noParameter2() { print("no parametr2, no return value") } noParameter() noParameter2() //no parametr, no return value //no parametr2, no return value ~~~ (2)多重输入参数,多参量函数(就是参数类型不一样) 函数可以有多个参数,写在圆括号中,用逗号分隔 ~~~ //三个输入参数 func multipleParameter(age : Int, name : String, sex : String) { print("Person name is \(name), age is \(age), sex is \(sex)") } multipleParameter(22, name: "Tom", sex: "boy") //Person name is Tom, age is 22, sex is boy ~~~ (3)多重返回值函数 可以⽤元组(tuple)类型让多个值作为⼀个复合值从函数中返回。 ~~~ func returnTuple(name : String, englishScore : Double, mathScore : Double, chineseScore : Double) -> (describe : String, averageScore : Double) { return ("name is " + name + ",englishScore is " + String(englishScore) + ",mathScore is " + String(mathScore) + ",chineseScore is " + String(chineseScore), (mathScore + englishScore + chineseScore) / 3) } var receive = returnTuple("dzl", englishScore: 70, mathScore: 80, chineseScore: 90) print("\(receive.describe), average is \(receive.1)") //两种访问元组元素的方式 //name is dzl,englishScore is 70.0,mathScore is 80.0,chineseScore is 90.0, average is 80.0 ~~~ 3、函数参数名称 函数参数都有⼀个外部参数名(external parameter name)和⼀个本地参数名(local parameter name).外部参数名⽤来标记传递给函数调⽤的参数,本地参数名在实现函数的时 候使⽤ 如(3)中例子 ⼀般情况下,第⼀个参数省略其外部参数名,第⼆个以后的参数使⽤其本地参数名作为⾃⼰的外部参数名.所有参数需要有不同的本地参数名,但可以共享相同的外部参数名 (1)指定外部参数名: 如1中例子 (2)忽略外部参数名: 如果你不想为第⼆个及后续的参数设置参数名,⽤⼀个下划线(_)代替⼀个明确地参数名 ~~~ func ignoreParatemer(name : String, _ age : Int){ print("test ignore parameter, name is \(name), age is \(age)") } ignoreParatemer("dzl", 22) //test ignore parameter, name is  dzl, age is 22 ~~~ (3)默认参数值 可以在函数体中为每个参数定义 默认值(Deafult Values)  。当默认值被定义后,调⽤这个函数时可以忽略这个参数 注意: 将带有默认值的参数放在函数参数列表的最后。这样可以保证在函数调⽤时,⾮默认参数的顺序是⼀致的,同时使得相同的函数在不同情况下调⽤时显得更为清晰 ~~~ func defaultValue(name : String, englishScore : Double, mathScore : Double = 80.00, chineseScore : Double = 90.00) { print("name is \(name), englishScore is \(englishScore), mathScore is \(mathScore), chineseScore is \(chineseScore)") } //三种调用方式 defaultValue("dzl", englishScore: 60) defaultValue("dzl", englishScore: 65, mathScore: 81) defaultValue("dzl", englishScore: 70, mathScore: 85, chineseScore: 95) //三种输出 name is dzl, englishScore is 60.0, mathScore is 80.0, chineseScore is 90.0 name is dzl, englishScore is 65.0, mathScore is 81.0, chineseScore is 90.0 name is dzl, englishScore is 70.0, mathScore is 85.0, chineseScore is 95.0 ~~~ (4)可变参数 ⼀个 可变参数(variadic parameter)  可以接受零个或多个值。函数调⽤时,你可以⽤可变参数来传⼊不确定数量的输⼊参数。通过在变量类型名后⾯加⼊ (...)  的⽅式来定义可变参数。 ~~~ func changeableParameter(scores : Double ...){ var totalScore : Double = 0 for score in scores { totalScore += score } print("the average score is \(totalScore/Double(scores.count))") } changeableParameter(12.0, 34.0, 90.0, 32) changeableParameter(65, 70) //the average score is 42.0 //the average score is 67.5 ~~~ (5)常量参数和变量参数 函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。 但是,有时候,如果函数中有传⼊参数的变量值副本将是很有⽤的。你可以通过指定⼀个或多个参数为变量参数,从⽽避免⾃⼰在函数中定义新的变量。变量参数不是常量,你可以在函数中把它当做新的可修改副本来使⽤。 通过在参数名前加关键字  var  来定义变量参数: ~~~ func varParameter(var name : String, score : Double) { name += (":" + String(score)) //可以修改name的值 print(name) } varParameter("dzl", score: 90) //dzl:90.0 ~~~ (6)输入输出参数 变量参数,正如上⾯所述,仅仅能在函数体内被更改。如果你想要⼀个函数可以修改参数的值,并且想要在这些修改在函数调⽤结束后仍然存在,那么就应该把这个参数定义为输⼊输出参数(In-Out Parameters)。 定义⼀个输⼊输出参数时,在参数定义前加  inout  关键字。⼀个输⼊输出参数有传⼊函数的值,这个值被函数修改,然后被传出函数,替换原来的值。 你只能将变量作为输⼊输出参数。你不能传⼊常量或者字⾯量(literal value),因为这些量是不能被修改的。当传⼊的参数作为输⼊输出参数时,需要在参数前加 &  符,表⽰这个值可以被函数修改。 注意: 输⼊输出参数不能有默认值,⽽且可变参数不能⽤  inout  标记。如果你⽤inout  标记⼀个参数,这个参数不能被  var  或者  let  标记。 ~~~ func inoutParameter(inout a : Int, inout b : Int) { let temp = a a = b b = temp } var a = 10 var b = 20 print("a is \(a), b is \(b)") inoutParameter(&a, b: &b) print("a is \(a), b is \(b)") //a is 10, b is 20 //a is 20, b is 10 ~~~ 4、函数类型 每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成 例如: ~~~ func addTwoInts(a: Int, _ b: Int) -> Int { return a + b } func multiplyTwoInts(a: Int, _ b: Int) -> Int { return a * b } ~~~ 这个例⼦中定义了两个简单的数学函数: addTwoInts  和  multiplyTwoInts  。这两个函数都传⼊两个  Int  类型, 返回⼀个合适的 Int  值。 这两个函数的类型是  (Int, Int) -> Int  ,可以读作“这个函数类型,它有两个  Int  型的参数并返回⼀个  Int  型的值。 下⾯是另⼀个例⼦,⼀个没有参数,也没有返回值的函数: ~~~ func printHelloWorld() { print("hello, world") } ~~~ 这个函数的类型是: () -> void  ,或者叫“没有参数,并返回  Void  类型的函数”。 (1)使用函数类型 ~~~ func useFuncType(a : Int, _ b : Int) -> Int { return a + b } //定义⼀个叫做 varFuncType 的变量,类型是‘⼀个有两个 Int 型的参数并返回⼀个 Int 型的值的函数’,并让这个新变量指向 useFuncType 函数 var varFuncType : (Int, Int) -> Int = useFuncType //然后我们就可以用varFuncType来调用useFuncType函数了 print(varFuncType(10, 20)) //还可以让它自己推断变量类型 var varFuncType2 = useFuncType print(varFuncType2(100, 200)) //30 //300 ~~~ (2)函数类型作为参数类型 ~~~ func func1(a : Int, b : Int) -> Int { return a + b } func func2(a : Int, b : Int) -> Int { return a * b } func func3(funcParameter : (Int, Int) -> Int, a : Int, b : Int) { let result = funcParameter(a, b) print(result) } func3(func1, a: 10, b: 20) func3(func2, a: 10, b: 20) //30 //200 ~~~ (3)函数类型作为返回值 ~~~ func returnValue1(a : Int, b : Int) -> Int { return a + b } func returnValue2(a : Int, b : Int) -> Int { return a * b } func returnValue3(retFunc : Bool) -> (Int, Int) -> Int { if retFunc { return returnValue1 }else { return returnValue2 } } print(returnValue3(true)(10, 20)) print(returnValue3(false)(10, 20)) //30 //200 ~~~ 5、嵌套函数 前面你所⻅到的所有函数都叫全局函数(global functions),它们定义在全局域中。你也可以把函数定义在别的函数体中,称作嵌套函数(nested functions) 默认情况下,嵌套函数是对外界不可⻅的,但是可以被他们封闭函数(enclosing function)来调⽤。⼀个封闭函数也可以返回它的某⼀个嵌套函数,使得这个函数可以在其他域中被使⽤。 ~~~ func returnValue13(retFunc : Bool) -> (Int, Int) -> Int { //这两个函数对外是不可见的,但是可以通过returnValue13 访问 func returnValue11(a : Int, b : Int) -> Int { return a + b } func returnValue12(a : Int, b : Int) -> Int { return a * b } if retFunc { return returnValue11 }else { return returnValue12 } } print(returnValue13(true)(10, 20)) print(returnValue13(false)(10, 20)) //30 //200 ~~~
';

swift之控制转移语句,continue,break,fallthrough,return,带标签的语句

最后更新于:2022-04-01 11:39:44

~~~ import Foundation //continue //continue 语句可以告诉一个循环体立刻停止本次循环,重新开始下次循环,但并不结束整个循环 for i in 1...10 { //剔除偶数 if i%2 == 0 { continue } print("continue:\(i)") } //break //break语句会立刻结束整个控制流的执行,当我们想更早的结束一个switch代码块或者一个循环体时,都可以使用break for i in 1...10 { if i == 3 { break } print("循环语句中的break:\(i)") } for i in 1...3 { for j in 1...10 { if j == 3 { break } //只结束一重for循环 print("双重循环语句中的break:\(j)") } } //switch中break /* 当在⼀个 switch 代码块中使⽤ break 时,会⽴即中断该 switch 代码块的执⾏,并且跳转到 表⽰ switch 代码块结束的⼤括号( } )后的第⼀⾏代码。 这种特性可以被⽤来匹配或者忽略⼀个或多个分⽀。因为 Swift 的 switch 需要包含所有的 分⽀⽽且不允许有为空的分⽀,有时为了使你的意图更明显,需要特意匹配或者忽略某个 分⽀。那么当你想忽略某个分⽀时,可以在该分⽀内写上 break 语句。当那个分⽀被匹配 到时,分⽀内的 break 语句⽴即结束 switch 代码块。 */ var t1 = 2 switch t1 { case 1: print("匹配到了1") print("11111111") case 2: print("匹配到了2") break print("22222222") case 3: break default: print("啥都没有匹配到") } //fallthrough /* Swift 中的 switch 不会从上⼀个 case 分⽀落⼊到下⼀个 case 分⽀中。相反,只要第⼀个 匹配到的 case 分⽀完成了它需要执⾏的语句,整个 switch 代码块完成了它的执⾏。相⽐ 之下,C 语⾔要求你显⽰的插⼊ break 语句到每个 switch 分⽀的末尾来阻⽌⾃动落⼊到下 ⼀个 case 分⽀中。Swift 的这种避免默认落⼊到下⼀个分⽀中的特性意味着它的 switch 功能要⽐ C 语⾔的更加清晰和可预测,可以避免⽆意识地执⾏多个 case 分⽀从⽽引发的 错误。 如果你确实需要 C ⻛格的贯穿的特性,你可以在每个需要该特性的 case 分⽀中使 ⽤ fallthrough 关键字。下⾯的例⼦使⽤ fallthrough 来创建⼀个数字的描述语句。 */ var t2 = 2 switch t2 { case 1: print("贯穿:1") fallthrough case 2: print("贯穿:2") fallthrough case 3: print("贯穿:3") fallthrough default: print("贯穿default") } //带标签的语句 /* 在 Swift 中,你可以在循环体和 switch 代码块中嵌套循环体和 switch 代码块来创造复杂的 控制流结构。然⽽,循环体和 switch 代码块两者都可以使⽤ break 语句来提前结束整个⽅ 法体。因此,显⽰地指明 break 语句想要终⽌的是哪个循环体或者 switch 代码块,会很有 ⽤。类似地,如果你有许多嵌套的循环体,显⽰指明 continue 语句想要影响哪⼀个循环体 也会⾮常有⽤。 为了实现这个⺫的,你可以使⽤标签来标记⼀个循环体或者 switch 代码块,当使 ⽤ break 或者 continue 时,带上这个标签,可以控制该标签代表对象的中断或者执⾏。 产⽣⼀个带标签的语句是通过在该语句的关键词的同⼀⾏前⾯放置⼀个标签,并且该标签 后⾯还需带着⼀个冒号。 */ label1 : for i in 1...10 { for j in 1...10 { if j == 3 { break label1 //此时break结束了两层for循环 } print("带标签的语句:\(j)") } } //return 结束一个函数 func test(name str : String , age n : Int) -> Void { print("\(str),\(n)") if n > 20 { return } print("test") } test(name: "dzl", age: 25) ~~~ 输出: ~~~ continue:1 continue:3 continue:5 continue:7 continue:9 循环语句中的break:1 循环语句中的break:2 双重循环语句中的break:1 双重循环语句中的break:2 双重循环语句中的break:1 双重循环语句中的break:2 双重循环语句中的break:1 双重循环语句中的break:2 匹配到了2 贯穿:2 贯穿:3 贯穿default 带标签的语句:1 带标签的语句:2 dzl,25 Program ended with exit code: 0 ~~~
';

swift之switch续(元组,值绑定,where)

最后更新于:2022-04-01 11:39:42

~~~ import Foundation let point = (2, 2) switch point { case (0, 0): print("point is (0, 0)") case (_, 0): //_匹配所有可能的值 print("point is (_, 0)") case (0, _): print("point is (0, _)") case (0...3, 0...3): print("point is the scope of (0...3, 0...3)") default: print("not in the scope of ... ") } //值绑定 //case 分⽀的模式允许将匹配的值绑定到⼀个临时的常量或变量,这些常量或变量在该 //case 分⽀⾥就可以被引⽤了——这种⾏为被称为值绑定(value binding)。 let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): //匹配纵坐标是0的点,并将横坐标的值赋予x,下同 print("on the x-axis with an x value of \(x)") case (0, let y): print("on the y-axis with a y value of \(y)") case let (x, y): //匹配所有 print("somewhere else at (\(x), \(y))") } //case分支的模式可以使用where语句来判断额外的条件 let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: //匹配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") } ~~~ 输出: ~~~ point is the scope of (0...3, 0...3) on the x-axis with an x value of 2 (1, -1) is on the line x == -y Program ended with exit code: 0 ~~~
';

swift之数组(Array)、集合(Set)、字典(Dictionary)

最后更新于:2022-04-01 11:39:40

1、数组(Array): ~~~ import Foundation //数组 //新建一个数组 var array1 = [Int]() //空数组 里面没有元素 print(array1.count) array1.append(3) //添加元素 print(array1.count) array1 = [] //清空数组 print(array1.count) //新建一个带有默认值的数组 var array2 = [Float](count: 5, repeatedValue: 2.11) print(array2) var array3 = [Float](count: 2, repeatedValue: 3.22) print(array3) var array23 = array2 + array3 //合并两个类型相同的数组 print(array23) //新建指定数值的数组 var array4 : [String] = ["value1", "value2", "value3"] print(array4) //访问和修改数组值 var array5 = [String]() if array5.count == 0 { print("array5 is empty") } if array5.isEmpty { print("array5 is empty") } //添加数据项 array5.append("v1") array5 += ["v2"] array5 += ["v3", "v4"] print(array5) print(array5[0]) array5[0] = "v111" //改变值 print(array5) array5[1...3] = ["v123"] //3项 替换为1项 print(array5) array5.insert("v-insert", atIndex: 1) // 在某个具体索引之前添加数据项 print(array5) array5.removeAtIndex(2) // 按索引移除某一项 print(array5) //array5.removeFirst() 移除第一项 //array5.removeLast() 移除最后一项 array5.removeAll() //移除所有 print(array5) //遍历数组 var array6 = [1, 2, 3, 4, 5, 6] for item in array6 { print(item) } for (index, value) in array6.enumerate() { print("index:\(index),value:\(value)") } ~~~ 输出: ~~~ 0 1 0 [2.11, 2.11, 2.11, 2.11, 2.11] [3.22, 3.22] [2.11, 2.11, 2.11, 2.11, 2.11, 3.22, 3.22] ["value1", "value2", "value3"] array5 is empty array5 is empty ["v1", "v2", "v3", "v4"] v1 ["v111", "v2", "v3", "v4"] ["v111", "v123"] ["v111", "v-insert", "v123"] ["v111", "v-insert"] [] 1 2 3 4 5 6 index:0,value:1 index:1,value:2 index:2,value:3 index:3,value:4 index:4,value:5 index:5,value:6 Program ended with exit code: 0 ~~~ 2、集合(Set) ~~~ //set 集合 //用来存储相同数据类型,但是没有确定顺序,元素的值不能相同 var set1 = Set<String>() set1.insert("value1") set1.insert("value2") print(set1) set1.insert("value1") print(set1) set1 = [] //置空 print(set1) //用数组创建集合 var set2 : Set<String> = ["set21", "set22", "set23"] var set3 : Set<String> = ["set211", "set444", "set222", "set233", "set222"] print(set2) print(set3) //set3.isEmpty //set3.count //这两个和数组一样 set3.insert("set1") print(set3) set3.remove("set1") /* 你可以通过调⽤ Set 的 remove(_:) ⽅法去删除⼀个元素,如果该值是该 Set 的⼀个元素则删 除该元素并且返回被删除的元素值,否认如果该 Set 不包含该值,则返回 nil 。另 外, Set 中的所有元素可以通过它的 removeAll() ⽅法删除。 */ var isContain = set3.contains("set211") //遍历一个set for item in set3 { print(item) } //排序后输出 for item in set3.sort() { print(item) } //基本集合操作 var a : Set<Int> = [1, 3, 4, 6, 7, 8, 9] var b : Set<Int> = [2, 4, 5, 8] print(a) print(b) //交集 print(a.intersect(b)) //并集 print(a.union(b)) //a-b print(a.subtract(b)) //并集-交集 print(a.exclusiveOr(b)) //集合成员关系和相等 var c : Set<Int> = [1, 3] var d : Set<Int> = [1, 3] if c == d { print("c和d这两个集合相等") } if c.isSubsetOf(a) { print("a包含c") } if a.isSupersetOf(d) { print("a包含d") } if c.isDisjointWith(b) { print("c与b没有交集") } if c.isStrictSubsetOf(a) { print("c是a的子集合") } /* /// Returns true if the set is a subset of a finite sequence as a `Set`. @warn_unused_result public func isSubsetOf<S : SequenceType where S.Generator.Element == Element>(sequence: S) -> Bool /// Returns true if the set is a subset of a finite sequence as a `Set` /// but not equal. @warn_unused_result public func isStrictSubsetOf<S : SequenceType where S.Generator.Element == Element>(sequence: S) -> Bool */ //看上面定义可知 这两个的区别是isStrictSubsetOf 两个集合不能相等 isSubsetOf可以相等 if c.isSubsetOf(d) { print("--") } if c.isStrictSubsetOf(d){ print("++") } ~~~ 集合操作图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19ff3d01c.jpg) 输出: ~~~ ["value1", "value2"] ["value1", "value2"] [] ["set22", "set21", "set23"] ["set211", "set222", "set233", "set444"] ["set1", "set211", "set222", "set233", "set444"] set211 set222 set233 set444 set211 set222 set233 set444 [4, 9, 6, 7, 3, 1, 8] [5, 2, 4, 8] [4, 8] [2, 4, 9, 6, 7, 5, 3, 1, 8] [9, 6, 7, 3, 1] [2, 9, 6, 7, 5, 3, 1] c和d这两个集合相等 a包含c a包含d c与b没有交集 c是a的子集合 -- Program ended with exit code: 0 ~~~ 3、字典 ~~~ //字典 /* Swift 的字典使⽤ Dictionary<Key, Value> 定义,其中 Key 是字典中键的数据类型,Value是字典中对应于这些键所存储值的数据类型。 注意: ⼀个字典的 Key 类型必须遵循 Hashable 协议,就像 Set 的值类型。 我们也可以⽤ [Key: Value] 这样快捷的形式去创建⼀个字典类型。虽然这俩种形式功能上相同,但是后者是⾸选 */ //两种创建方式 var dict1 = [String : String]() var dict2 = Dictionary<String, String>() print(dict1) print(dict2) dict1["key1"] = "value1" print(dict1) dict1 = [:] //置空 print(dict1) var dict3 : [String : String] = ["key1":"value1", "key2":"value2", "key3":"value3"] print(dict3) //定义dict3的时候 [String : String] 可以省略 //字典基本操作 //dict3.isEmpty //dict3.count 判断是否为空 //增加 dict3["key4"] = "value4" print(dict3) //修改 dict3["key4"] = "value4444444" print(dict3) dict3.updateValue("valueNew4", forKey: "key4") print(dict3) //删除 dict3.removeValueForKey("key4") print(dict3) //遍历 for (key, value) in dict3 { print("\(key) : \(value)") } for key in dict3.keys { print(key) } for value in dict3.values { print(value) } for key in dict3.keys.sort() { print(dict3[key]!) } ~~~ 输出: ~~~ [:] [:] ["key1": "value1"] [:] ["key1": "value1", "key3": "value3", "key2": "value2"] ["key1": "value1", "key4": "value4", "key2": "value2", "key3": "value3"] ["key1": "value1", "key4": "value4444444", "key2": "value2", "key3": "value3"] ["key1": "value1", "key4": "valueNew4", "key2": "value2", "key3": "value3"] ["key1": "value1", "key2": "value2", "key3": "value3"] key1 : value1 key2 : value2 key3 : value3 key1 key2 key3 value1 value2 value3 value1 value2 value3 Program ended with exit code: 0 ~~~
';

swift之可选类型

最后更新于:2022-04-01 11:39:37

可选类型用来表示值缺失的情况 C和OC中没有可选类型这个概念 ~~~ //可选类型定义 var x : Int? var y : Int y = 10 print("\(x) -- \(y)") //输出:nil -- 10 ~~~ 如果注释掉  y = 10    则发生错误: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fe9babd.jpg) 但是可选类型就不会出错,因为如果声明了一个可选变量或者常量而没有赋值,则默认为nil nil不能用于非可选的常量或者变量 使用  !   号获取可选值 当你确定可选类型确实包含值之后,你可以在可选的名字后⾯加⼀个感叹号( !  )来获取值。这个惊叹号表⽰“我知道这个可选有值,请使⽤它。”这被称为可选值的 强制解析 ~~~ var str1 : String? = "myName" print("myName is \(str1)") print("myName is \(str1!)") ~~~ 输出: ~~~ myName is Optional("myName") myName is myName ~~~ 可选绑定: ~~~ /* 使⽤可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给⼀个 临时常量或者变量。可选绑定可以⽤在 if 和 while 语句中来对可选类型的值进⾏判断并把 值赋给⼀个常量或者变量。 */ var str2 : String? = "myStr2" if let str2Sub = str2 { print(str2Sub) }else{ print("无值") } //输出:myStr2 //如果str2可选类型包含一个值,就创建一个str2Sub的变量,并将可选包含的值赋给他 ~~~ 隐式解析可选类型 ~~~ /* 如上所述,可选类型暗⽰了常量或者变量可以“没有值”。可选可以通过 if 语句来判断是否 有值,如果有值的话可以通过可选绑定来解析值。 有时候在程序架构中,第⼀次被赋值之后,可以确定⼀个可选类型总会有值。在这种情况 下,每次都要判断和解析可选值是⾮常低效的,因为可以确定它总会有值。 这种类型的可选状态被定义为隐式解析可选类型(implicitly unwrapped optionals)。把 想要⽤作可选的类型的后⾯的问号( String? )改成感叹号( String! )来声明⼀个隐式解 析可选类型。 */ var str3 : String! str3 = "myStr33333333" print(str3) //不需要用!取值 //输出:myStr33333333 ~~~
';

oc与swift混编,OC调用swift,swift调用OC

最后更新于:2022-04-01 11:39:35

1、oc工程调用swift-----自动创建桥接头文件 创建一个oc工程: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19f4a5341.jpg) 设置Product Module Name = 工程名 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fbc037c.jpg) 创建一个swift文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fc0443b.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fc52a3a.jpg) 点击自动创建桥接头文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fc9a0d1.jpg) 设置Objective-C Bridging Header 如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fcc7bbf.jpg) 至此,我们可以在oc中调用swift了 测试代码: ~~~ import Foundation class Student: NSObject { var name : String = "dzl" var age : Int = 22 } ~~~ 在oc中引入头文件  "工程名-swift.h" 就可以使用swift中的类了 注:这个头文件是不可见的 ~~~ #import "ViewController.h" #import "OCuseSwift1-swift.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. Student * s1 = [[Student alloc] init]; NSLog(@"%@", s1.name); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ~~~ 输出: ~~~ 2015-11-13 10:01:32.250 OCuseSwift1[1040:20007] dzl ~~~ 此时swift也是可以引用OC的,只需将swift需要使用的oc类头文件在桥接头文件中引入即可, ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fd130d7.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fd38a01.jpg) 2、oc工程调用swift-----手动创建桥接头文件 首先创建一个oc工程,与上面相同 然后创建一个swift文件,但是不选择创建桥接头文件,如图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fd7691c.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fda7337.jpg) 然后手动创建桥接头文件,就相当于创建一个普通的头文件一样,只是命名一定要严格按照规则: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fdd5f1c.jpg) 工程设置中指定桥接头文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572b19fe2a110.jpg) 经测试,oc引用swift或者swift引用oc都是可以的,测试方法与上面相同,这里不再赘述。 3、swift工程调用-----自动创建桥接头文件 和 手动创建桥接头文件,基本与上面操作一直,不再详述 其实桥接头文件里面引入oc头文件,是为了swift可以访问oc文件, 在oc中引入   工程名-swift.h   文件  是为了oc可以访问swift,但这个文件是不可见的,不过可以通过command+鼠标左键查看该文件
';

swift之 元组

最后更新于:2022-04-01 11:39:33

~~~ import Foundation //元组(tuples)把多个值组合成⼀个复合值。元组内的值可以是任意类型,并不要求是相同类型 var value1 = ("dzl", 10, true) //任意顺序的任意类型都可以组成一个元组 //元组内容分解 var (value1Sub1, value1Sub2, value1Sub3) = value1 //value1Sub1 = "dzl" value1Sub2 = 10 value1Sub3 = true //如果你只需要⼀部分元组值,分解的时候可以把要忽略的部分⽤下划线( _ )标记: var (value1Sub11, _, value1Sub31) = value1 //可以通过下表访问元素 print(value1.0) //可以在定义元组的时候给元素命名 var value2 = (name:"dzl", age:12, sex:true) //此时可以通过元素名字来取值 print(value2.age) ~~~
';

swift之数值类型杂谈(数值)

最后更新于:2022-04-01 11:39:31

~~~ import Foundation //整数,没有小数部分,有正数有负数 /* Swift 提供了8,16,32和64位的有符号和⽆符号整数类型。这些整数类型和 C 语⾔的命 名⽅式很像,⽐如8位⽆符号整数类型是 UInt8 ,32位有符号整数类型是 Int32 。就像 Swift 的其他类型⼀样,整数类型采⽤⼤写命名法。 */ var x8 : Int8 = 10 var x16 : Int16 = 10 var x32 : Int32 = 0 var x64 : Int64 = -10 var ux8 : UInt16 = 20 //不再多说 //整数范围 var minInt32 = Int32.min var maxInt32 = Int32.max print("int32.min = \(minInt32), int32.max = \(maxInt32)") //int32.min = -2147483648, int32.max = 2147483647 /* ⼀般来说,不需要专⻔指定整数的⻓度。Swift 提供了⼀个特殊的整数类型 Int ,⻓度与 当前平台的原⽣字⻓相同: 在32位平台上 Int 和 Int32长度相同 在64位平台上 Int 和 Int64长度相同 UInt 也是一样 在32位平台上 UInt 和 UInt32长度相同 在64位平台上 UInt 和 UInt64长度相同 尽量不要使⽤ UInt ,除⾮你真的需要存储⼀个和当前平台原⽣字⻓相同的⽆符号整 数。除了这种情况,最好使⽤ Int ,即使你要存储的值已知是⾮负的。统⼀使 ⽤ Int 可以提⾼代码的可复⽤性,避免不同类型数字之间的转换 */ //浮点数 /* Double 表⽰64位浮点数。当你需要存储很⼤或者很⾼精度的浮点数时请使⽤此类型。 Float 表⽰32位浮点数。精度要求不⾼的话可以使⽤此类型。 Double 精确度很⾼,⾄少有15位数字,⽽ Float 最少只有6位数字。选择哪个类型取 决于你的代码需要处理的值的范围。 */ //类型推断 /* Swift 是⼀个类型安全(type safe)的语⾔。类型安全的语⾔可以让你清楚地知道代码要 处理的值的类型。如果你的代码需要⼀个 String ,你绝对不可能不⼩⼼传进去⼀个 Int 。 由于 Swift 是类型安全的,所以它会在编译你的代码时进⾏类型检查(type checks),并 把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。 当你要处理不同类型的值时,类型检查可以帮你避免错误。然⽽,这并不是说你每次声明 常量和变量的时候都需要显式指定类型。如果你没有显式指定类型,Swift 会使⽤_类型推 断(type inference)来选择合适的类型。有了类型推断,编译器可以在编译代码的时候 ⾃动推断出表达式的类型。原理很简单,只要检查你赋的值即可 */ let value1 = 15 //value1会被推断为Int let value2 = 12.88 //value2会被推断为Double // 当推断浮点数的类型时,Swift 总是会选择 Double ⽽不是 Float let value3 = 2 + 11.00 //valuew3 会被推断为Double //因为:如果表达式中同时出现了整数和浮点数,会被推断为 Double 类型 //数值类型: /* ⼀个⼗进制数,没有前缀 ⼀个⼆进制数,前缀是 0b ⼀个⼋进制数,前缀是 0o ⼀个⼗六进制数,前缀是 0x */ let decimalInteger = 17 let binaryInteger = 0b10001 // ⼆进制的17 let octalInteger = 0o21 // ⼋进制的17 let hexadecimalInteger = 0x11 // ⼗六进制的17 print("十进制:\(decimalInteger), 二进制:\(binaryInteger), 八进制:\(octalInteger), 十六进制:\(hexadecimalInteger)") //十进制:17, 二进制:17, 八进制:17, 十六进制:17 //如果⼀个⼗进制数的指数为 exp ,那这个数相当于基数和10^exp的乘积: var testEXP = 3.33e5 // = 333000 var testEXPfu = 3.33e-2 print("\(testEXP) - \(testEXPfu)") //输出:333000.0 - 0.0333 var testexp2 = 0xAp3 // = 10 * (2 * 2 * 2) = 80 var testexp2fu = 0xap-3 print("\(testexp2) - \(testexp2fu)") //输出:80.0 - 1.25 //数值类字⾯量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字⾯量: let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_1 //下划线和0不会影响原有值 //数值类型转换 /* 不同整数类型的变量和常量可以存储不同范围的数字。 Int8 类型的常量或者变量可以存储 的数字范围是 -128 ~ 127 ,⽽ UInt8 类型的常量或者变量能存储的数字范围是 0 ~ 255 。如 果数字超出了常量或者变量可存储的范围,编译的时候会报错: let cannotBeNegative: UInt8 = -1 // UInt8 类型不能存储负数,所以会报错 let tooBig: Int8 = Int8.max + 1 // Int8 类型不能存储超过最⼤值的数,所以会报错 由于每种整数类型都可以存储不同范围的值,所以你必须根据不同情况选择性使⽤数值型 类型转换。这种选择性使⽤的⽅式,可以预防隐式转换的错误并让你的代码中的类型转换 意图变得清晰。 要将⼀种数字类型转换成另⼀种,你要⽤当前值来初始化⼀个期望类型的新数字,这个数 字的类型就是你的⺫标类型。在下⾯的例⼦中,常量 twoThousand 是 UInt16 类型,然⽽常 量 one 是 UInt8 类型。它们不能直接相加,因为它们类型不同。所以要调⽤ UInt16(one) 来 创建⼀个新的 UInt16 数字并⽤ one 的值来初始化,然后使⽤这个新数字来计算: */ var twoThousand: UInt16 = 2_000 var one: UInt8 = 1 var twoThousandAndOne = twoThousand + UInt16(one) //整数和浮点类型的转换 var valueInt = 12 var valueDouble = 10.11 var valueTotal = Double(valueInt) + valueDouble print(valueTotal) //输出:22.11 var valueTotalToInt = Int(valueTotal) print(valueTotalToInt) //输出:22 //此时会发生截断 //类型别名 typealias DZL = Int32 var t1 : DZL = 111 //布尔值 //Swift 有两个布尔常量, true 和 false var boolType : Bool = true ~~~
';

swift之声明常量和变量

最后更新于:2022-04-01 11:39:29

~~~ import Foundation print("Hello, World!") //var 定义变量 //swift每条语句结尾可以使用分号也可以不用 var x = 1.0 //一行中可以定义多个相同类型的变量 var y = 2, z = 3 var yy, zz:Double //let 定义常量 let name = "dzl" //变量赋值之后可以更改为别的同类型的值,但是常量赋值之后就不能更改了 //声明常量或者变量的时候,可以加上类型标注,说明常量或者变量需要存储的值的类型 var age : Int = 25 let sex : String = "男" //我们可以⽤任何自己喜欢的字符作为常量和变量名,包括 Unicode 字符: var 变量1 = 12 var π = "测试" //常量与变量名不能包含数学符号,箭头,保留的(或者⾮法的)Unicode 码位,连线与制表符。也不能以数字开头,但是可以在常量与变量名的其他地⽅包含数字。 //输出: print("age is " + String(age)) print("age is \(age)") /* Hello, World! age is 25 age is 25 Program ended with exit code: 0 */ ~~~
';

swift控制语句,for,while,repeat-while,if,switch

最后更新于:2022-04-01 11:39:26

if   switch   for   while ~~~ <div>import Foundation //for循环 for i in 1...5 {    print("(闭区间)标准for in :\(i)") } for i in 1..<5 {    print("(半开区间)标准for in :\(i)") } //其中 i 是每次循环开始时被自动赋值的常量,这种情况下 i 不需要提前声明,只需要将它包含在循环的声明中,就可以对其进行隐式声明 //如果不需要知道区间内的每一项的值,可以使用下划线 _ 替代变量名来忽略对值的访问 var result1 = 1 for _ in 1...5 {    result1 *= 2 } print("for 不访问每一项的值:\(result1)") //for in 遍历数组 var indexs = ["111", "222", "333"] for index in indexs {    print("for 遍历数组:\(index)") } //for in 遍历字典 var dicts = ["key1":"value1", "key2":"value2", "key3":"value3"] for (key, value) in dicts {    print("for 遍历字典:\(key) : \(value)") } //标准for循环 for var i = 0; i < 3; i++ {    print("标准for循环:\(i)") } //while循环 var i = 0 while i < 3 {    print("标准while:\(i)")    i++ } // i 需要定义并且初始化 //repeat-while //先执行循环体,再执行条件语句   类似于do while var j = 0 repeat {    print("repeat while : \(j)")    j++ } while j < 3 //if 语句 var age = 10 if age < 10 {    print("年龄小于10") }else if age == 10 {    print("年龄等于10") }else {    print("年龄大于10") } //switch 语句 let someCharacter: Character = "e" switch someCharacter { case "a", "e", "i", "o", "u":    print("\(someCharacter) 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("\(someCharacter) is a consonant") default:    print("\(someCharacter) is not a vowel or a consonant") } //与 C 语⾔和 Objective-C 中的 switch  语句不同,在 Swift 中,当匹配的 case 分⽀中的代 //码执⾏完毕后,程序会终⽌ switch  语句,⽽不会继续执⾏下⼀个 case 分⽀。这也就是 //说,不需要在 case 分⽀中显式地使⽤ break  语句。这使得 switch  语句更安全、更易⽤,也 //避免了因忘记写 break  语句⽽产⽣的错误。 //switch 匹配区间 let day = 1234 switch day {    case 1...100:      //... 闭区间        print("这个天数很小")    case 101..<1_000:  //..< 半开区间        print("这个天数不小了")    case 1_000...10_000:        print("这个天数有点大")    default:        print("不知道这个天数在哪个区间") }</div> ~~~ 输出: ~~~ <div>(闭区间)标准for in :1 (闭区间)标准for in :2 (闭区间)标准for in :3 (闭区间)标准for in :4 (闭区间)标准for in :5 (半开区间)标准for in :1 (半开区间)标准for in :2 (半开区间)标准for in :3 (半开区间)标准for in :4 for 不访问每一项的值:32 for 遍历数组:111 for 遍历数组:222 for 遍历数组:333 for 遍历字典:key1 : value1 for 遍历字典:key3 : value3 for 遍历字典:key2 : value2 标准for循环:0 标准for循环:1 标准for循环:2 标准while:0 标准while:1 标准while:2 repeat while : 0 repeat while : 1 repeat while : 2 年龄等于10 e is a vowel 这个天数有点大 Program ended with exit code: 0</div> ~~~
';

前言

最后更新于:2022-04-01 11:39:24

> 原文出处:[swift学习笔记](http://blog.csdn.net/column/details/swift0.html) 作者:[lvdezhou](http://blog.csdn.net/lvdezhou) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # swift学习笔记 > The swift programming language 2.0 学习笔记,包含大部分swift基础知识,持续更新。。。
';