Hello World:html
print(Hello World)
本文已使用Swift3更新。v3的主要更新見Swift 3 更新ios
// 常量變量 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, Optionalobjective-c
集合類型: Array, Set, Dictionaryswift
複合類型: Tuple, Functionsegmentfault
命名類型: Class, Struct, Enum, Protocol數組
Int(UInt, Int, UInt8(16,32,64), Int8(16,32,64), UInt8.min, UInt8.max), 32位平臺Int爲Int32, 64爲Int64, UInt同理閉包
String類型支持Unicode. Unicode標量寫成u{n} ("u{24}","u{1F496}")app
Double(64位浮點)、Float(32位浮點)框架
typealias AudioSample = UInt16 var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound如今是0
元組類型使用逗號隔開並使用括號括起來的0個或多個類型組成的列表less
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, 0, 0.1, 0.2, 0.3] var talkList = ["ha", "xi", "mi", "ga", "he", "wa"] talkList[2...4] = ["hehe", "yoyo"] // 利用下標來一次改變一系列數據值 talkList // ["ha", "xi", "hehe", "yoyo", "wa"] talkList.insert("kao", at: 0) // ["kao", "ha", "xi", "hehe", "yoyo", "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,Int,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 提供恆等===和不恆等!==
請注意,「等價於」(用三個等號表示,===)與「等於」(用兩個等號表示,==)的不一樣:
「等價於」表示兩個類類型(class type)的常量或者變量引用同一個類實例。
「等於」表示兩個實例的值「相等」或「相同」,斷定時要遵守設計者定義的評判標準,所以相對於「相等」來講,這是一種更加合適的叫法。
空合運算符(a ?? b): 表達式a必須是Optional類型默認值,b的類型必需要和a存儲值的類型保持一致, 是對如下代碼的簡短表達方法
a != nil ? a! : b
與C語言中的算術運算符不一樣,Swift中的算術運算符默認是不會溢出的,若是容許溢出行爲,使用溢出運算符(&+,&-,&*)
當基礎類型(整形、浮點、布爾等)沒有值時,是不能使用的。一個Optional值未經初始化時爲nil。
var str: String? //未被初始化,nil var nIndex: Int? = 2 //初始化爲2,Optional(2)
使用!來獲取一個不存在的可選值會致使運行時錯誤。使用!來強制解析值以前,必定要肯定可選包含一個非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 a {...}將報錯,a不會隱形地與 0 作對比
guard的執行取決於一個表達式的布爾值。咱們可使用guard語句來要求條件必須爲真時,以執行guard語句後的代碼。不一樣於if語句,一個guard語句老是有一個else分句,若是條件不爲真則執行else分句中的代碼。
switch中匹配到的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.") }
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
你能夠在循環中使用 「..<」,「...」 來表示範圍,也可使用傳統的寫法,二者是等價的
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,3,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, 4, 3, 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:能夠訪問同一模塊源文件中的任何實體,在模塊外也能夠經過導入該模塊來訪問源文件裏的全部實體。一般狀況下,框架中的某個接口能夠被任何人使用時,你能夠將其設置爲 public 級別。
internal:能夠訪問同一模塊源文件中的任何實體,可是不能從模塊外訪問該模塊源文件中的實體。一般狀況下,某個接口只在應用程序或框架內部使用時,你能夠將其設置爲 internal 級別。
private:限制實體只能在所在的源文件內部使用。使用 private 級別能夠隱藏某些功能的實現細節。
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 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 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) 會在這裏被調用,即做用域的最後。 } }