Swift 编程语言学习
Hello World: print(Hello World) 本文已使用Swift3更新。v3的主要更新见Swift 3 更新 快速上手// 常量变量 let constVar = "100" var value = 0 var red,green,blue: Double // 数组 var str1 = "AAA" var str2 = "BBB" var array:[String] = [str1,str2] array.append("CCC") for str in array { print("str: (str)") } var myStr = array[2] // 字典 var dict:[String: String] = ["Key1":"Val1","Key2":"Val2"] dict["Key3"] = "Val3" dict["Key2"] = nil // delete Key2 for (key,val) in dict { print("key: (key),value:(val)") } // 枚举 enum CollisionType: Int { case Player = 1 case Enemy = 2 } var type = CollisionType.Player // 函数 func doIt() -> Int { return 0 } func doIt(a:Int,b:Int) -> Int { return a+b } // 类 class Shape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } deinit { // 析构函数,如果你需要 } func simpleDescription() -> String { return "(self.name) with (numberOfSides) sides." } } var shape = Shape(name: "Box") shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription() print(shapeDescription) // Box with 7 sides. 类型基本类型: nil,Int,Float/Double,Bool,String,Optional 集合类型: Array,Set,Dictionary 复合类型: Tuple,Function 命名类型: Class,Struct,Enum,Protocol Int(UInt,UInt8(16,32,64),Int8(16,UInt8.min,UInt8.max),32位平台Int为Int32,64为Int64,UInt同理 String类型支持Unicode. Unicode标量写成u{n} ("u{24}","u{1F496}") Double(64位浮点)、Float(32位浮点) 类型别名(type aliases)typealias AudioSample = UInt16 var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound现在是0 元组元组类型使用逗号隔开并使用括号括起来的0个或多个类型组成的列表 var a = (1,2,”haha”) 集合类型Swift的Array类型被桥接到Foundation中的NSArray类 var someInts = [Int]() // 空数组 var threeDoubles = [Double](repeating:0.0,count: 3) // [0.0,0.0,0.0] var sixDoubles = threeDoubles + [0.1,0.2,0.3] // [0,0.1,0.3] var talkList = ["ha","xi","mi","ga","he","wa"] talkList[2...4] = ["hehe","yoyo"] // 利用下标来一次改变一系列数据值 talkList // ["ha","hehe","yoyo","wa"] talkList.insert("kao",at: 0) // ["kao","ha","wa"] Swift的Set类型被桥接到Foundation中的NSSet类 var letters = Set<Character>() print("letters is of type Set<Character> with (letters.count) items.") letters.insert("a") letters = [] // letters 现在是一个空的 Set,但是它依然是 Set<Character> 类型 // 使用数组字面量来构造集合 var favoriteGenres: Set<String> = ["Rock","Classical","Hip hop"] 集合类型的哈希值,比如a==b,因此必须a.hashValue == b.hashValue,Swift 的所有基本类型(比如String,Double和Bool)默认都是可哈希化的 Swift的Dictionary类型被桥接到Foundation的NSDictionary类。 let airports = ["YYZ": "Toronto Pearson","LHR": "London Heathrow"] let airportCodes = [String](airports.keys) // ["LHR","YYZ"] let airportNames = [String](airports.values) // ["London Heathrow","Toronto Pearson"] 运算符Swift 支持 C 语言中的全部位运算符 Swift 中是可以对浮点数进行求余的 8 % 2.5 // Swift3不在支持 8.truncatingRemainder(dividingBy: 2.5) // Swift3 Swift 提供恒等===和不恒等!== 请注意,“等价于”(用三个等号表示,===)与“等于”(用两个等号表示,==)的不同:
空合运算符(a ?? b): 表达式a必须是Optional类型默认值,b的类型必须要和a存储值的类型保持一致,是对以下代码的简短表达方法 a != nil ? a! : b 与C语言中的算术运算符不同,Swift中的算术运算符默认是不会溢出的,如果允许溢出行为,使用溢出运算符(&+,&-,&*) Optional类型当基础类型(整形、浮点、布尔等)没有值时,是不能使用的。一个Optional值未经初始化时为nil。 var str: String? //未被初始化,nil var nIndex: Int? = 2 //初始化为2,Optional(2) 强制解析(forced unwrapping)使用!来获取一个不存在的可选值会导致运行时错误。使用!来强制解析值之前,一定要确定可选包含一个非nil的值。 if convertedNumber != nil { // 输出 "convertedNumber has an integer value of 123." print("convertedNumber has an integer value of (convertedNumber!).") } 隐式解析let possibleString: String? = "An optional string." let forcedString: String = possibleString! // 需要惊叹号来获取值 let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // 不需要感叹号 if assumedString != nil { print(assumedString) // 输出 "An implicitly unwrapped optional string." } if let definiteString = assumedString { print(definiteString) // 输出 "An implicitly unwrapped optional string." } 可选链式调用// residence为optional类型,无论numberOfRooms属性是否为optional类型,roomCount将为Int? if let roomCount = john.residence?.numberOfRooms { print("John's residence has (roomCount) room(s).") } else { print("Unable to retrieve the number of rooms.") } 可选链式调用提供了另一种访问numberOfRooms的方式,使用问号(?)来替代原来的叹号(!),在residence后面添加问号之后,Swift 就会在residence不为nil的情况下访问numberOfRooms. 注意,Dictionary类型的键的下标返回可选类型值,故可以用可选链式调用 var testScores = ["key1": [86,82,84],"key2": [79,94,81]] testScores["key2"]?[0]++ 流程控制条件和循环变量的括号可以省略,语句体的大括号是必须的if语句条件必须是一个布尔表达式,if a {...}将报错,a不会隐形地与 0 做对比 guard的执行取决于一个表达式的布尔值。我们可以使用guard语句来要求条件必须为真时,以执行guard语句后的代码。不同于if语句,一个guard语句总是有一个else分句,如果条件不为真则执行else分句中的代码。 Switch-Caseswitch中匹配到的case子句之后,程序会退出switch语句,并不会继续向下运行,所以不需要在每个子句结尾写break,如果需要贯穿可以用 fallthrough let vegetable = "red pepper" switch vegetable { // Is it a spicy red pepper? case "celery": print("Add some raisins and make ants on a log.") case "cucumber","watercress": print("That would make a good tea sandwich.") case let x where x.hasSuffix("pepper"): print("Is it a spicy (x)?") default: print("Everything tastes good in soup.") } while循环 (while,repeat-while)var n = 2 while n < 100 { n = n * 2 } print(n) // 128 var m = 2 repeat { m = m * 2 } while m < 100 print(m) // 128 for循环你可以在循环中使用 “..<”,“...” 来表示范围,也可以使用传统的写法,两者是等价的 var nLoop1 = 0 for var i = 0; i <= 3; ++i { // Swift3中已移除这种C风格的for,且移除了++操作符 nLoop1 += i } var nLoop2 = 0 for i in 0...3 { // 包含3,如果用..<就不包含3 nLoop2 += i } 函数用func声明函数,swift中函数为一级类型 // ->后为返回值 func greet(name: String,day: String) -> String { return "Hello (name),today is (day)." } // 使用元组可以返回多个返回值 func getGasPrices() -> (Double,Double,Double) { return (3.59,3.69,3.79) } // 可变形参 func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum } print(sumOf(numbers: 2,3,1)) // 6 // 函数是一级类型,这意味着可以作为参数传递 func hasAnyMatches(list: [Int],condition: (Int) -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20,19,7,12] hasAnyMatches(list: numbers,condition: lessThanTen) // true // 指定外部参数名 func sayHello(to person: String,and anotherPerson: String) -> String { return "Hello (person) and (anotherPerson)!" } print(sayHello(to: "Bill",and: "Ted")) // prints "Hello Bill and Ted!" // 如果你不想为参数设置外部参数名,用一个下划线(_)代替一个明确的参数名。 // 注意,因为第一个参数默认忽略其外部参数名称,显式地写下划线是多余的。 func someFunction(_ firstParameterName: Int,_ secondParameterName: Int) { } someFunction(1,3) 注意,没有返回值的函数具有隐式的返回类型Void(或者说是空元组) 运算符函数类和结构体可以为现有的运算符提供自定义的实现,这通常被称为运算符重载。 struct Vector2D { var x = 0.0,y = 0.0 } func + (left: Vector2D,right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x,y: left.y + right.y) } let vector = Vector2D(x: 3.0,y: 1.0) let anotherVector = Vector2D(x: 2.0,y: 4.0) let combinedVector = vector + anotherVector // combinedVector 是一个新的 Vector2D 实例,值为 (5.0,5.0) 前缀和后缀运算符: func关键字之前指定 prefix 或者 postfix 修饰符 prefix func - (vector: Vector2D) -> Vector2D { return Vector2D(x: -vector.x,y: -vector.y) } 复合赋值运算符: 复合赋值运算符将赋值运算符(=)与其它运算符进行结合(如+=)。在实现的时候,需要把运算符的左参数设置成inout类型,因为这个参数的值会在运算符函数内直接被修改。 func += (inout left: Vector2D,right: Vector2D) { left = left + right } 注意,不能对默认的赋值运算符(=)进行重载。只有组合赋值运算符可以被重载。同样地,也无法对三目条件运算符 (a ? b : c) 进行重载。 自定义运算符: 新的运算符要使用 operator 关键字在全局作用域内进行定义,同时还要指定 prefix、infix 或者 postfix 修饰符: prefix operator +++ {} 结合性的默认值是 none,优先级的默认值 100。参考 闭包函数是一个特殊的闭包,swift的闭包可以理解为其他语言的类似lambda表达式,形式: {(parameters) -> returnType in statements } // closure var numbers = [2,4,5] var a = numbers.map({ (number: Int) -> Int in let result = 3 * number return result }) print(a) // [6,9,12,15] // 更简单的方式: 闭包参数类型已知 var b = numbers.map({ number in 3 * number }) // 根据参数位置 let sortedNumbers = numbers.sort { $0 > $1 } print(sortedNumbers) // [5,2] 类构造函数为init,如果需要,用self来区分属性 如果你需要在删除对象之前进行一些清理工作,使用deinit创建一个析构函数 属性里可以添加get/set,新值名默认为newValue 如果你不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码,使用willSet和didSet 继承:class Square: NamedShape {},调用父类属性或方法使用super.XXX 子类如果要重写父类的方法的话,必须用override标记 延迟存储属性来避免复杂类中不必要的初始化: lazy 标记为final来防止它们被重写 下标脚本 struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index } } let threeTimesTable = TimesTable(multiplier: 3) print("six times three is (threeTimesTable[6])") // 输出 "six times three is 18" 处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?。如果?之前的值是nil,?后面的东西都会被忽略,并且整个表达式返回nil。否则,?之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。 let optionalSquare: Square? = Square(sideLength: 2.5,name: "optional Square") let sideLength = optionalSquare?.sideLength 类型转化检查类型:用 is 向下转型:用类型转换操作符(as? 或 as!) AnyObject 可以表示任何类类型的实例 Any 可以表示任何类型,包括函数类型 访问控制对类、结构体、枚举可以设置访问级别。
public 为最高(限制最少)访问级别,private 为最低(限制最多)访问级别。默认为 internal 级别。另外,子类的访问级别不得高于父类的访问级别、元组访问级别为成员里最低级别。 枚举和结构体使用enum来创建一个枚举。就像类和其他所有命名类型一样,枚举可以包含方法 enum Suit { case Spades,Hearts,Diamonds,Clubs func description() -> String { switch self { case .Spades: return "spades" case .Hearts: return "hearts" case .Diamonds: return "diamonds" case .Clubs: return "clubs" } } } let hearts = Suit.Hearts let heartsDescription = hearts.description() 枚举成员可以有实例值,相同枚举成员的实例可以有不同的值。创建实例的时候传入值即可。实例值和原始值是不同的:枚举成员的原始值对于所有实例都是相同的,而且你是在定义枚举的时候设置原始值。 enum ServerResponse { case Result(String,String) case Error(String) } let success = ServerResponse.Result("6:00 am","8:09 pm") let failure = ServerResponse.Error("Out of cheese.") switch success { case let .Result(sunrise,sunset): let serverResponse = "Sunrise is at (sunrise) and sunset is at (sunset)." print(serverResponse) case let .Error(error): let serverResponse = "Failure... (error)" print(serverResponse) } 结构体和类基本类似,但最大一个区别在于结构体是传值,类是传引用。 struct Card { var suit: Suit func description() -> String { return "The Card is suit of (suit.description)" } } 协议和拓展protocol使用protocol来声明一个协议。类、枚举和结构体都可以实现协议。 protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " Now 100% adjusted." } } 实现协议中的 mutating 方法时,若是类类型,则不用写mutating关键字。而对于结构体和枚举,则必须写 mutating 关键字。 类只能单继承,协议的实现可以同时实现多个。并且协议间可以相互继承,并也能多继承。在协议继承列表中,添加class声明只能被类采纳。 class SomeClass: SomeSuperClass,FirstProtocol,AnotherProtocol {/*...*/} protocol InheritingProtocol: SomeProtocol,AnotherProtocol {/*...*/} 协议只指定属性的名称和类型,还指定属性是只读的还是可读可写的。指定方法时不需要大括号和方法体。 协议可以指定构造器,只是在实现类中要添加required 协议前添加@objc,表示只能被objective-c的类或@objc类采纳。 extension使用extension来为现有的类型添加功能,比如新的方法和计算属性。你可以使用扩展在别处修改定义,甚至是从外部库或者框架引入的一个类型,使得这个类型遵循某个协议。 extension Int: ExampleProtocol { var simpleDescription: String { return "The number (self)" } mutating func adjust() { self += 42 } } print(7.simpleDescription) 泛型在尖括号里写一个名字来创建一个泛型函数或者类型。你也可以创建泛型函数、方法、类、枚举和结构体。 func repeatItem<Item>(item: Item,numberOfTimes: Int) -> [Item] { var result = [Item]() for _ in 0..<numberOfTimes { result.append(item) } return result } repeatItem(item: "knock",numberOfTimes:4) // Reimplement the Swift standard library's optional type enum OptionalValue<Wrapped> { case None case Some(Wrapped) } var possibleInteger: OptionalValue<Int> = .None possibleInteger = .Some(100) 关联类型定义一个协议时,通过 typealias 关键字来指定关联类型。 protocol A { typealias ItemType /*采用ItemType的一些方法*/ } class SubA : A { typealias ItemType = Int } 错误处理func canThrowAnError() throws { // 这个函数有可能抛出错误 } // 抛出错误消息,catch捕捉 do { try canThrowAnError() // 没有错误消息抛出 } catch { // 有一个错误消息抛出 } 将错误转换成可选值func someThrowingFunction() throws -> Int {/*...*/} // someThrowingFunction()抛出一个错误,x和y的值是nil let x = try? someThrowingFunction() let y: Int? do { y = try someThrowingFunction() } catch { y = nil } 禁用错误传递let photo = try! loadImage("./Resources/John Appleseed.jpg") // 禁用错误传递 指定清理操作使用defer语句在即将离开当前代码块时执行一系列语句 func processFile(filename: String) throws { if exists(filename) { let file = open(filename) defer { close(file) } while let line = try file.readline() { // 处理文件。 } // close(file) 会在这里被调用,即作用域的最后。 } } 资料
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |