一.常量和變量
[代碼]
let maximumNumberOfLoginAtAttempts = 10 #用let聲明常量
var currentLoginAttempt = 0 #用var聲明變量
[類型注釋]
聲明常量或者變量的時候提供類型注釋,明確存儲值的類型。常量或者變量名后依次添加 冒號,空格,類型名稱來實現(xiàn)。
var welcomeMessage: String
welcomeMessage = "Hello"
其實,可以不適用類型注釋,因為在給常量或者變量提供初始值的時候,swift可以推測出他的類型。
[打?。? println(welcomeMessage) #打印變量
#字符串插值 用“ \(變量名) ” 來占位,swift會用變量的值來替換這個占位符
println("The current value of welcomeMessage is \(welcomeMessage)")
二.注釋和分號
[注釋]
//單行注釋
/*多行 注釋*/
[分號]
語句結(jié)束后不需要;去標志結(jié)束
但是如果多個語句寫在一行,可以使用分號去分割
三.整數(shù)和浮點數(shù)
[整數(shù)]
swift提供 8 16 32 64位有符號和無符號的整數(shù)
Eg.
UInt8 8位無符號整數(shù)
Int32 32位有符號整數(shù)
let minValue = UInt8.min
let maxValue = UInt8.max
在swift中,UInt , Int類型 與 當前系統(tǒng)的字長相等,
32位系統(tǒng),Int === Int32
64位系統(tǒng),Int === Int64
[浮點數(shù)]
Double 64位浮點數(shù)
Float 32位浮點數(shù)
四.類型安全和類型推斷
類型安全:編譯的時候會進行類型檢查,標記不匹配的類型。
類型推斷:根據(jù)初值推斷類型
[數(shù)字的字面量]
不帶前綴的十進制數(shù)
0b前綴的二進制數(shù)
0o前綴的八進制數(shù)
0x前綴的十六進制數(shù)
[指數(shù)]
1.25e2 --> 1.25 * (10^2) #10進制基數(shù)是以10為底
1.25e-2 --> 1.25 * (10^-2)
0xFp2 --> 15 * (2^2) #16進制基數(shù)是以2為底
[數(shù)值類型的轉(zhuǎn)化]
整數(shù)間的轉(zhuǎn)化demo:
let twoThousand: UInt16 = 2_000 #_不會改變字面值,輔助提高可讀性
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one) #加號兩邊都是UInt16可以相加
浮點數(shù)的轉(zhuǎn)化demo
let three = 3
let pointNum = 3.1415
let pi = Double(three) + pointNum
let intPI = Int(pi)
上面這種SomeType(ofInitialValue) [eg. Double(three) ]
是一種調(diào)用swift類型構(gòu)造器的默認方法,我們?yōu)樗麄魅氤踔?,比?UInt16 的構(gòu)造器可以用來接收UInt8類型的值,
所以可以將UInt8類型的值轉(zhuǎn)化成UInt16,此處必須傳UInt16支持的類型,不是隨便什么類型都可以的。當然可以通過擴展讓構(gòu)造器支持自定義類型。
[類型別名]
typealias AudioSample = UInt16
var maxUInt16Num = AudioSample.max #UInt16.max
五.布爾值
[聲明和初始化]
let oragesAreOrange = true #不需要制指定具體的Bool類型,編 譯器會幫助我們推斷的
let oragesAreOrange = false
[判斷語句與Bool]
錯誤寫法:編譯器不允許非bool值替換Bool,這個跟java等其他語言不同
let i = 1
if i {
}
正確寫法:
if i==1 {}
六.元組Tuple
多個值組合成一個復合值,元組中的值可以是任何類型,并且可以是相互不同的類型。
場景:比如一個處理訪問網(wǎng)頁響應(yīng)的函數(shù),需要返回(Int,String)元組來描述成功失敗的結(jié)果。
let http404Error = (404,"Not Found") #類型是 (Int , String)
#下標訪問
println("The status code is \(http404Error.0)") #The status code is 404
println("The status msg is \(http404Error.1)") #The status msg is Not Found
let http200Status = (statusCode:200,description:"OK")
#元素名稱訪問
println("The status code is \(http200Status.statusCode)") #The status code is 200
println("The status msg is \(http200Status.description)") #The status msg is OK
let (statusCode,statusMsg) = http404Error
println("The status code is \(statusCode)") #The status code is 404
println("The status msg is \(statusMsg)") #The status msg is Not Found
let (justTheStatueCode, _) = http404Error # 用( _ ) 來忽略不關(guān)心的部分
println("The status code is \(justTheStatueCode)") #The status code is 404
七.Optional類型
Optional 類型是swift獨有的 ,表示一個基礎(chǔ)類型可能有值也可能沒有值,當他沒有值的時候就是nil。
[Optional定義]
定義一個Optional的值很容易,只需要在類型后面加上問號(?)就行了:
var str : String?
[顯式拆包]
Optional類型的值不能被直接使用,當需要用時要顯式拆包,以表明我知道這個Optional是一定有值的,拆包用?。? var str: String? = "Hello World!"
str! //Hello World!
ps,Optional類型其實是一個枚舉
[隱式拆包]
除了顯式拆包,Optional還提供了隱式拆包,通過在聲明時的數(shù)據(jù)類型后面加一個感嘆號(!)來實現(xiàn):
var str: String! = "Hello World!"
str //Hello World!
[可選綁定Optional Binding]
如下兩個demo來講述一下為甚么要Optiona Binding:
看下面這個demo,當count != nil條件成真后接著在上下文中使用count,會被要求進行拆包 String(count!) ,
var count: Int?
count = 100
if count != nil {
"count is " + String(count!) //count is 100
} else {
"nil"
}
為了避免在條件判斷語句后執(zhí)行一次或更多次的拆包,Swift引進了Optional Binding,我們就可以這樣做:
var count: Int?
count = 100
if let validCount = count {
"count is " + String(validCount) //count is 100
} else {
"nil"
}
[Optional Chaining]
暫時還沒辦法秒懂,mark一下,回頭看
http://blog.csdn.net/zhangao0086/article/details/38640209
八.斷言
用于運行時校驗對應(yīng)條件是否等于true的判斷。
let age = -3
assert(age>=0,"A person age can not less than zero")
只有斷言的條件 age>=0的時候 才會繼續(xù)執(zhí)行,否則 age是負數(shù) 斷言是false 那么就會觸發(fā)斷言 程序終止。
九.運算符
賦值 let b = 10
算數(shù) + - * /
取余 %
這個符號要特殊說明一下,因為他與別的語言的取模不一樣,他表示( a%b) a中包括多少個b 并返回剩余的值,公式是
a = (b * some multiplier) + remainder
9 = (4 * 2) + 1 [9 % 4 = 1]
-9=(4 * -2) + -1 [-9 % 4 = -1] #可見 跟正負號沒甚么關(guān)系
8 = (2.5 * 3) + 0.5 #浮點數(shù)也一樣的
自增 ++
自減 --
var a = 0
let b = ++a # b = 1 ; a = 1
let c = a++ # c = 1 ; a = 2
一元減 - 理解成負號
一元加 + 對操作數(shù)沒甚么變化
復合賦值運算 +=
比較運算符 相等(a==b) 不相等(a!=b) 大于(a>b) 小于(a<b)
大于等于(a>=b) 小于等于(a<=b) 完全等(===) 不完全等(!==)
三元條件 question ? answer1 : answer2
范圍運算符 閉合范圍運算符
for index in 1...5 {} #[1,5]
半閉合范圍運算符
for index in 1..5 {} #[1,5)
邏輯運算符 邏輯非 !a
邏輯與 a &&
邏輯或 a || b
十.字符串和字符
[初始化空字符串]
var emptyString = ""
var anotherEmptyString = String()
if emptyString.isEmpty { #判斷字符串為空
emptyString += "給字符串加點內(nèi)容"
}
string是拷貝類型,即 賦值,參數(shù)傳遞等 string值是生成一個副本的,不是原始的版本。與Cocoa的NSString不同。
[字符]
let yenSign: Character = "¥" #需要類型注釋 和 字面量
for character in "一個字符串" {
println(character)
}
#countElements統(tǒng)計字符數(shù),全局函數(shù)
let unusualMsg = "slfjasfjslafjasfj"
println("\(countElements(unusualMsg))")
[字符串的比較]
字面值相等 if str1 == str2 { ...... }
前綴相等 if str1.hasPrefix("Act 1") { ........ }
后綴相等 if str1.hasSuffix("Act 1") { ........ }
字符串大寫 let strUpper = str.uppercaseString
字符串小寫 let strLower = str.lowercaseString
[Unicode]
關(guān)于Unicode 和 三種兼容unicode的字符串 自行查找資料進一步學習~
三種兼容字符串是:UTF-8 編碼單元集合 for c in str.utf8 { ... }
UTF-16編碼單元集合 for c in str.utf16 { ... }
21位Unicode標量值的結(jié)合 for c in str.unicodeScalars { ... }
十一.集合
集合有兩類:
數(shù)組:相同類型的有序列表
字典:相同類型的無序列表
[數(shù)組定義]
var shoppingList: String[] = ["Eggs","Milk"]
var shoppingList: Array<String> = ["Eggs","Milk"]
var shoppingList = ["Eggs","Milk"] #類型推斷的存在,可以不用定義類型
var someInts = Int[] () #空數(shù)組
var someInts = [] #空數(shù)組
#構(gòu)造器,創(chuàng)建有若干默認值的數(shù)組
var threeDoubles = Double[] (count:3 ,repeatedValue: 0.0)
var anotherThreeDoubles = Array(count:3 ,repeatedValue: 2.5)
var sixDoubles = threeDoubles + anotherThreeDoubles
[數(shù)組操作]
shoppingList.count #元素個數(shù)
shoppingList.isEmpty #是否為空
shoppingList.append("flower") #追加元素
shoppingList += "Baking Powder" #添加元素
shoppingList +=["str1","str2"] #添加多個
var firstItem = shoppingList[0] #獲取第一個元素
shoppingList[0] = "Egg2016" #修改
shoppingList[4...6] = ["huhu","fafa"] #修改下標4到6的三個元素為 huhu , fafa
shoppingList.insert("tomato",atIndex: 0) #在指定位置插入
let mapleSyrup = shoppingList.removeAtIndex(0) #刪除index位置的元素
let apples = shoppingList.removeLast() #刪除最后一個元素,他會避免對count屬性的查詢,推薦使用這個 而不是 removeAtIndex(count-1)
[數(shù)組的遍歷]
for item in shoppingList { ... }
#enumerate為每個元素返回一個元組
for (index,value) in enumerate(shoppingList) {
println("item \(index+1) : \(value) ")
}
[字典的定義]
var airports: Dictionary<String,String> = ["a":"b","c":"d"]
var airports = ["a":"b","c":"d"]
var airports = Dictionary<Int,String>() #空字典
airports = [:] # 空字典字面量[:],前提是字典已經(jīng)指定了類型
[字典的操作]
airports["e"] = "f" #追加,如果key不存在
airports["e"] = "g" #修改,如果key存在
#updateValue更新某個key對應(yīng)的值,返回字典值類型的可選
if let oldValue = airports.updateValue("new value", forKey:"a") {
println("\(oldValue)")
}
#刪除鍵值對
airports["APL"] = nil #通過設(shè)置值為nil來刪除鍵值對
if let removedValue = airports.removeValueForKey("a"){
println(" \(removedValue) ")
}else {
println("does not contain value for key a")
}
[字典的遍歷]
for (airportCode,airportName) in airports {
}
for airportCode in airports.keys { .... }
for airportName in airports.values { .... }
let airportCodes = Array(airports.keys)
let airportValues = Array(airports.values)
十二.流程控制
[for index in 集合]
for index in 1...5 { ... }
for _ in 1...n { ... } #下劃線來占位,前提是 你需要用到集合中的元素值
for arrItem in oneArray { ... }
for (code,msg) in oneDic { ... }
for character in "Hello" { ... }
=================================
[for 循環(huán)]
for var index = 0;index < 3; ++index { .... }
=================================
[while 循環(huán)]
while a < b {
a++
}
do{
a++
} while a<b
=================================
[if 語句]
if condition {
...
}else if condition {
...
}else {
...
}
=================================
[switch 語句]
swift不需要break去結(jié)束一個case執(zhí)行,當然你也可以寫,一個case命中執(zhí)行后就結(jié)束了,不會跳轉(zhuǎn)到下一個case。注意,每個case必須要有至少一條執(zhí)行語句,不能是空的 會編譯報錯。
let someCharacter: Character = "e"
switch someCharacter {
case "a","b","c":
println("\(someCharacter) is a vowel")
case "d","e","f":
println("\(someCharacter) is a constant")
default:
println("default")
}
關(guān)于case支持的格式:
范圍匹配 case 1...3:
元組匹配 let somePoint = (1,1)
switch somePoint {
case (0,0):
println("(0,0) is at the origin")
case (_,0):
println("用_來匹配任何可能的值")
case (-2...2,-2...2):
println("用范圍來匹配值")
default:
println("默認命中")
}
值綁定 switch somePoint {
case (let x,0):
println("\(x) 被綁定了橫坐標命中的值")
case let(x,y):
println("獲取綁定的值 ( \(x),\(y) ) ")
default:
println("默認命中")
}
where分句檢測額外條件
switch somePoint {
case let(x,y) where x==y:
println("綁定的值 ( \(x),\(y) ) on the line x == y ")
default:
println("默認命中")
}
=================================
[控制轉(zhuǎn)移語句]
continue 停止現(xiàn)在的工作繼續(xù)下次迭代
break 終止整個流程
fallthrough switch執(zhí)行一個case后會結(jié)束此次switch,用fall through會執(zhí)行下一個case
switch m {
case "a":
XXXXXXX
fall through
case "b":
XXXXXXXX
default:
XXXXXXXX
}
標簽語句
gameLoop: ******
continue gameLoop
十三.函數(shù)
[定義]
# ->指定函數(shù)的返回值
func sayHello (personName: String) -> String {
let greeting = "Hello," + personName + "!"
}
[參數(shù)]
#多參,返回多個返回值
func count(str: String,str2: String) -> (vowels: Int,consonants: Int,others: Int){
return (vowels, consonants, others)
}
#外參,外部參數(shù)名可以在函數(shù)調(diào)用的時候?qū)τ趨?shù)有更加直觀的認識。即該參數(shù)名對外部可見。
import Foundation
func sayHello(username name:String)->String{
let result = "Hello," + name
return result
}
var nickname:String = "Jack"
println(sayHello(username: nickname)) #調(diào)用
#同時可以使某個參數(shù)名同時是內(nèi)部參數(shù)名和外部參數(shù)名:使用#號。
func sayHello(#name:String)->String{
let result = "Hello," + name
return result
}
var nickname:String = "Jack"
println(sayHello(name: nickname))
#默認行參值,swift會給你定義的默認行參提供一個自動外部名,比如joiner 會有一個外部名 joiner,跟加#類似
fun join(str1: String,str2: String,joiner: String = "") -> String {
return str1 + joiner + str2
}
join("hello","world")
#
十四.閉包
十五.枚舉
[定義]
enum CompassPoint {
case North
case South
case East
case West
}
var directionToHead = CompassPoint.West #directionToHead就是CompassPoint類型的變量
directionToHead = .East #directionToHead的類型是已知的了,所以你可以忽略它的類型來給他賦值了
[使用Switch語句來匹配枚舉值]
directionToHead = .South
switch directionToHead {
case .North:
println("Lots of planets have a north")
case .South:
println("Watch out for penguins")
case .East:
println("Where the sun rises")
case .West:
println("Where the skies are blue")
}
[關(guān)聯(lián)值]
enum Barcode {
case UPCA(Int, Int, Int)
case QRCode(String)
}
定義了一個叫做Barcode的枚舉類型,它可以有一個UPCA成員,這個成員關(guān)聯(lián)了一個包含三個整型數(shù)值的元組,同時這個枚舉類型還有一個QRCode成員,關(guān)聯(lián)了一個字符串。
var productBarcode = Barcode.UPCA(8, 85909_51226, 3) ??梢杂萌我馄渲幸粋€類型來生成一個新的
productBarcode = .QRCode("ABCDEFGHIJKLMNOP") #還可以被賦值為另一個類型,一旦定義了變量類型,再次賦值的時候不需要帶類型Barcode
switch productBarcode
{
case .UPCA(let numberSystem, let identifier, let check): #let可以提前 let .UPCA(numberSystem, identifier, check)
println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
case .QRCode(let productCode): #let .QRCode(productCode)
println("QR code with value of \(productCode).")
}
[原始值]
enum ASCIIControlCharacter: Character {
case Tab = "\t"
case LineFeed = "\n"
case CarriageReturn = "\r"
}
enum Planet: Int {
case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
let earthsOrder = Planet.Earth.toRaw() #toRaw()方法來獲取他的原始值,eathsOrder is 3
let possiblePlanet = Planet.fromRaw(7) #fromRaw()方法來嘗試通過一個原始值來尋找他所對應(yīng)的枚舉成員
# possiblePlanet is of type Planet? and equals Planet.Uranus”
# possiblePlanet是一個Planet?類型,可能會是nil,因此需要判斷:
let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) { ??蛇x綁定
switch somePlanet {
case .Earth:
println("ostly harmless")
default:
println("Not a safe place for humans")
}
} else {
println("There isn't a planet at position \(positionToFind)") #Planet.fromRaw(positionToFind) 如果是 nil ,那么就會走到這
}
十六.類和結(jié)構(gòu)體
反饋一個問題:
binary operator === can not be applied
[swift語言詳解]http://c.biancheng.net/cpp/html/2427.html 在數(shù)組的===比較這一塊是錯誤的,恒等用在引用類型上,而數(shù)組是值類型,可以看下這個demo:

Paste_Image.png
[定義]
struct Resolution { #Resolution的結(jié)構(gòu)體,用來描述一個顯示器的像素分辨率
var width = 0
var heigth = 0
}
class VideoMode { #VideoMode的類,用來描述一個視頻顯示器的特定模式
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
let someResolution = Resolution()
let vga = resolution(width:640, heigth: 480)
let someVideoMode = VideoMode()
someVideoMode.resolution.width = 12880
print(someResolution.width)
[屬性]
存儲屬性:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
延遲存儲屬性:
延遲存儲屬性是指當?shù)谝淮伪徽{(diào)用的時候才會計算其初始值的屬性。在屬性聲明前使用@lazy來標示一個延遲存儲屬性。
必須將延遲存儲屬性聲明成變量(使用var關(guān)鍵字),因為屬性的值在實例構(gòu)造完成之前可能無法得到。
class DataImporter {
/*
DataImporter 是一個將外部文件中的數(shù)據(jù)導入的類。
這個類的初始化會消耗不少時間。
*/
var fileName = "data.txt"
// 這是提供數(shù)據(jù)導入功能
}
class DataManager {
@lazy var importer = DataImporter()
var data = String[]()
// 這是提供數(shù)據(jù)管理功能
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// DataImporter 實例的 importer 屬性還沒有被創(chuàng)建
DataManager的一個功能是從文件導入數(shù)據(jù),該功能由DataImporter類提供,DataImporter需要消耗不少時間完成初始化:因為它的實例在初始化時可能要打開文件,還要讀取文件內(nèi)容到內(nèi)存。DataManager也可能不從文件中導入數(shù)據(jù)。所以當DataManager的實例被創(chuàng)建時,沒必要創(chuàng)建一個DataImporter的實例,更明智的是當用到DataImporter的時候才去創(chuàng)建它。由于使用了@lazy,importer屬性只有在第一次被訪問的時候才被創(chuàng)建。比如訪問它的屬性fileName時:
println(manager.importer.fileName)
// DataImporter 實例的 importer 屬性現(xiàn)在被創(chuàng)建了
// 輸出 "data.txt”
計算屬性:
類、結(jié)構(gòu)體和枚舉可以定義計算屬性,計算屬性不直接存儲值,而是提供一個 getter 來獲取值,一個可選的 setter 來間接設(shè)置其他屬性或變量的值。
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) { #(newCenter) 可以省略不寫,用默認的newValue
origin.x = newCenter.x - (size.width / 2) #origin.x = newValue.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
square.center = Point(x: 15.0, y: 15.0)
println("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// 輸出 "square.origin is now at (10.0, 10.0)”
屬性監(jiān)視器:
暫時不知道哪里用到,先不說了
類型屬性:
略