一.常量和變量
[代碼]
let maximumNumberOfLoginAtAttempts = 10 #用let聲明常量
var currentLoginAttempt = 0 #用var聲明變量
[類型注釋]
聲明常量或者變量的時(shí)候提供類型注釋撮抓,明確存儲(chǔ)值的類型站超。常量或者變量名后依次添加 冒號(hào)蒸苇,空格县昂,類型名稱來實(shí)現(xiàn)七芭。
var welcomeMessage: String
welcomeMessage = "Hello"
其實(shí),可以不適用類型注釋,因?yàn)樵诮o常量或者變量提供初始值的時(shí)候辩昆,swift可以推測(cè)出他的類型术辐。
[打印]
println(welcomeMessage) #打印變量
#字符串插值 用“ \(變量名) ” 來占位瑞躺,swift會(huì)用變量的值來替換這個(gè)占位符
println("The current value of welcomeMessage is \(welcomeMessage)")
二.注釋和分號(hào)
[注釋]
//單行注釋
/*多行 注釋*/
[分號(hào)]
語句結(jié)束后不需要;去標(biāo)志結(jié)束
但是如果多個(gè)語句寫在一行,可以使用分號(hào)去分割
三.整數(shù)和浮點(diǎn)數(shù)
[整數(shù)]
swift提供 8 16 32 64位有符號(hào)和無符號(hào)的整數(shù)
Eg.
UInt8 8位無符號(hào)整數(shù)
Int32 32位有符號(hào)整數(shù)
let minValue = UInt8.min
let maxValue = UInt8.max
在swift中曼振,UInt , Int類型 與 當(dāng)前系統(tǒng)的字長(zhǎng)相等,
32位系統(tǒng),Int === Int32
64位系統(tǒng)抛人,Int === Int64
[浮點(diǎn)數(shù)]
Double 64位浮點(diǎn)數(shù)
Float 32位浮點(diǎn)數(shù)
四.類型安全和類型推斷
類型安全:編譯的時(shí)候會(huì)進(jìn)行類型檢查,標(biāo)記不匹配的類型。
類型推斷:根據(jù)初值推斷類型
[數(shù)字的字面量]
不帶前綴的十進(jìn)制數(shù)
0b前綴的二進(jìn)制數(shù)
0o前綴的八進(jìn)制數(shù)
0x前綴的十六進(jìn)制數(shù)
[指數(shù)]
1.25e2 --> 1.25 * (10^2) #10進(jìn)制基數(shù)是以10為底
1.25e-2 --> 1.25 * (10^-2)
0xFp2 --> 15 * (2^2) #16進(jìn)制基數(shù)是以2為底
[數(shù)值類型的轉(zhuǎn)化]
整數(shù)間的轉(zhuǎn)化demo:
let twoThousand: UInt16 = 2_000 #_不會(huì)改變字面值,輔助提高可讀性
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one) #加號(hào)兩邊都是UInt16可以相加
浮點(diǎn)數(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)造器的默認(rèn)方法酷鸦,我們?yōu)樗麄魅氤踔掂诹眩热?UInt16 的構(gòu)造器可以用來接收UInt8類型的值,
所以可以將UInt8類型的值轉(zhuǎn)化成UInt16,此處必須傳UInt16支持的類型,不是隨便什么類型都可以的拼卵。當(dāng)然可以通過擴(kuò)展讓構(gòu)造器支持自定義類型壤蚜。
[類型別名]
typealias AudioSample = UInt16
var maxUInt16Num = AudioSample.max #UInt16.max
五.布爾值
[聲明和初始化]
let oragesAreOrange = true #不需要制指定具體的Bool類型聪富,編 譯器會(huì)幫助我們推斷的
let oragesAreOrange = false
[判斷語句與Bool]
錯(cuò)誤寫法:編譯器不允許非bool值替換Bool,這個(gè)跟java等其他語言不同
let i = 1
if i {
}
正確寫法:
if i==1 {}
六.元組Tuple
多個(gè)值組合成一個(gè)復(fù)合值,元組中的值可以是任何類型奸披,并且可以是相互不同的類型。
場(chǎng)景:比如一個(gè)處理訪問網(wǎng)頁(yè)響應(yīng)的函數(shù),需要返回(Int,String)元組來描述成功失敗的結(jié)果。
let http404Error = (404,"Not Found") #類型是 (Int , String)
#下標(biāo)訪問
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獨(dú)有的 ,表示一個(gè)基礎(chǔ)類型可能有值也可能沒有值司蔬,當(dāng)他沒有值的時(shí)候就是nil。
[Optional定義]
定義一個(gè)Optional的值很容易,只需要在類型后面加上問號(hào)(?)就行了:
var str : String?
[顯式拆包]
Optional類型的值不能被直接使用跛十,當(dāng)需要用時(shí)要顯式拆包,以表明我知道這個(gè)Optional是一定有值的,拆包用>础:
var str: String? = "Hello World!"
str! //Hello World!
ps,Optional類型其實(shí)是一個(gè)枚舉
[隱式拆包]
除了顯式拆包,Optional還提供了隱式拆包刽严,通過在聲明時(shí)的數(shù)據(jù)類型后面加一個(gè)感嘆號(hào)(!)來實(shí)現(xiàn):
var str: String! = "Hello World!"
str //Hello World!
[可選綁定Optional Binding]
如下兩個(gè)demo來講述一下為甚么要Optiona Binding:
看下面這個(gè)demo管削,當(dāng)count != nil條件成真后接著在上下文中使用count崎弃,會(huì)被要求進(jìn)行拆包 String(count!) 线婚,
var count: Int?
count = 100
if count != nil {
"count is " + String(count!) //count is 100
} else {
"nil"
}
為了避免在條件判斷語句后執(zhí)行一次或更多次的拆包,Swift引進(jìn)了Optional Binding游沿,我們就可以這樣做:
var count: Int?
count = 100
if let validCount = count {
"count is " + String(validCount) //count is 100
} else {
"nil"
}
[Optional Chaining]
暫時(shí)還沒辦法秒懂唇敞,mark一下咒精,回頭看
http://blog.csdn.net/zhangao0086/article/details/38640209
八.斷言
用于運(yùn)行時(shí)校驗(yàn)對(duì)應(yīng)條件是否等于true的判斷。
let age = -3
assert(age>=0,"A person age can not less than zero")
只有斷言的條件 age>=0的時(shí)候 才會(huì)繼續(xù)執(zhí)行,否則 age是負(fù)數(shù) 斷言是false 那么就會(huì)觸發(fā)斷言 程序終止渠啊。
九.運(yùn)算符
賦值 let b = 10
算數(shù) + - * /
取余 %
這個(gè)符號(hào)要特殊說明一下拄氯,因?yàn)樗c別的語言的取模不一樣镣煮,他表示( a%b) a中包括多少個(gè)b 并返回剩余的值邮弹,公式是
a = (b * some multiplier) + remainder
9 = (4 * 2) + 1 [9 % 4 = 1]
-9=(4 * -2) + -1 [-9 % 4 = -1] #可見 跟正負(fù)號(hào)沒甚么關(guān)系
8 = (2.5 * 3) + 0.5 #浮點(diǎn)數(shù)也一樣的
自增 ++
自減 --
var a = 0
let b = ++a # b = 1 ; a = 1
let c = a++ # c = 1 ; a = 2
一元減 - 理解成負(fù)號(hào)
一元加 + 對(duì)操作數(shù)沒甚么變化
復(fù)合賦值運(yùn)算 +=
比較運(yùn)算符 相等(a==b) 不相等(a!=b) 大于(a>b) 小于(a<b)
大于等于(a>=b) 小于等于(a<=b) 完全等(===) 不完全等(!==)
三元條件 question ? answer1 : answer2
范圍運(yùn)算符 閉合范圍運(yùn)算符
for index in 1...5 {} #[1,5]
半閉合范圍運(yùn)算符
for index in 1..5 {} #[1,5)
邏輯運(yùn)算符 邏輯非 !a
邏輯與 a &&
邏輯或 a || b
十.字符串和字符
[初始化空字符串]
var emptyString = ""
var anotherEmptyString = String()
if emptyString.isEmpty { #判斷字符串為空
emptyString += "給字符串加點(diǎn)內(nèi)容"
}
string是拷貝類型夜牡,即 賦值影所,參數(shù)傳遞等 string值是生成一個(gè)副本的阴幌,不是原始的版本。與Cocoa的NSString不同议忽。
[字符]
let yenSign: Character = "¥" #需要類型注釋 和 字面量
for character in "一個(gè)字符串" {
println(character)
}
#countElements統(tǒng)計(jì)字符數(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的字符串 自行查找資料進(jìn)一步學(xué)習(xí)~
三種兼容字符串是:UTF-8 編碼單元集合 for c in str.utf8 { ... }
UTF-16編碼單元集合 for c in str.utf16 { ... }
21位Unicode標(biāo)量值的結(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)建有若干默認(rèn)值的數(shù)組
var threeDoubles = Double[] (count:3 ,repeatedValue: 0.0)
var anotherThreeDoubles = Array(count:3 ,repeatedValue: 2.5)
var sixDoubles = threeDoubles + anotherThreeDoubles
[數(shù)組操作]
shoppingList.count #元素個(gè)數(shù)
shoppingList.isEmpty #是否為空
shoppingList.append("flower") #追加元素
shoppingList += "Baking Powder" #添加元素
shoppingList +=["str1","str2"] #添加多個(gè)
var firstItem = shoppingList[0] #獲取第一個(gè)元素
shoppingList[0] = "Egg2016" #修改
shoppingList[4...6] = ["huhu","fafa"] #修改下標(biāo)4到6的三個(gè)元素為 huhu , fafa
shoppingList.insert("tomato",atIndex: 0) #在指定位置插入
let mapleSyrup = shoppingList.removeAtIndex(0) #刪除index位置的元素
let apples = shoppingList.removeLast() #刪除最后一個(gè)元素润樱,他會(huì)避免對(duì)count屬性的查詢嗅钻,推薦使用這個(gè) 而不是 removeAtIndex(count-1)
[數(shù)組的遍歷]
for item in shoppingList { ... }
#enumerate為每個(gè)元素返回一個(gè)元組
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更新某個(gè)key對(duì)應(yīng)的值基茵,返回字典值類型的可選
if let oldValue = airports.updateValue("new value", forKey:"a") {
println("\(oldValue)")
}
#刪除鍵值對(duì)
airports["APL"] = nil #通過設(shè)置值為nil來刪除鍵值對(duì)
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é)束一個(gè)case執(zhí)行,當(dāng)然你也可以寫,一個(gè)case命中執(zhí)行后就結(jié)束了怎栽,不會(huì)跳轉(zhuǎn)到下一個(gè)case谬以。注意邮丰,每個(gè)case必須要有至少一條執(zhí)行語句娃循,不能是空的 會(huì)編譯報(bào)錯(cuò)吹泡。
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("默認(rèn)命中")
}
值綁定 switch somePoint {
case (let x,0):
println("\(x) 被綁定了橫坐標(biāo)命中的值")
case let(x,y):
println("獲取綁定的值 ( \(x),\(y) ) ")
default:
println("默認(rèn)命中")
}
where分句檢測(cè)額外條件
switch somePoint {
case let(x,y) where x==y:
println("綁定的值 ( \(x),\(y) ) on the line x == y ")
default:
println("默認(rèn)命中")
}
=================================
[控制轉(zhuǎn)移語句]
continue 停止現(xiàn)在的工作繼續(xù)下次迭代
break 終止整個(gè)流程
fallthrough switch執(zhí)行一個(gè)case后會(huì)結(jié)束此次switch,用fall through會(huì)執(zhí)行下一個(gè)case
switch m {
case "a":
XXXXXXX
fall through
case "b":
XXXXXXXX
default:
XXXXXXXX
}
標(biāo)簽語句
gameLoop: ******
continue gameLoop
十三.函數(shù)
[定義]
# ->指定函數(shù)的返回值
func sayHello (personName: String) -> String {
let greeting = "Hello," + personName + "!"
}
[參數(shù)]
#多參揭朝,返回多個(gè)返回值
func count(str: String,str2: String) -> (vowels: Int,consonants: Int,others: Int){
return (vowels, consonants, others)
}
#外參,外部參數(shù)名可以在函數(shù)調(diào)用的時(shí)候?qū)τ趨?shù)有更加直觀的認(rèn)識(shí)锋恬。即該參數(shù)名對(duì)外部可見彤悔。
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í)可以使某個(gè)參數(shù)名同時(shí)是內(nèi)部參數(shù)名和外部參數(shù)名:使用#號(hào)卵佛。
func sayHello(#name:String)->String{
let result = "Hello," + name
return result
}
var nickname:String = "Jack"
println(sayHello(name: nickname))
#默認(rèn)行參值,swift會(huì)給你定義的默認(rèn)行參提供一個(gè)自動(dòng)外部名疾牲,比如joiner 會(huì)有一個(gè)外部名 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)
}
定義了一個(gè)叫做Barcode的枚舉類型,它可以有一個(gè)UPCA成員谴忧,這個(gè)成員關(guān)聯(lián)了一個(gè)包含三個(gè)整型數(shù)值的元組很泊,同時(shí)這個(gè)枚舉類型還有一個(gè)QRCode成員,關(guān)聯(lián)了一個(gè)字符串沾谓。
var productBarcode = Barcode.UPCA(8, 85909_51226, 3) #可以用任意其中一個(gè)類型來生成一個(gè)新的
productBarcode = .QRCode("ABCDEFGHIJKLMNOP") #還可以被賦值為另一個(gè)類型均驶,一旦定義了變量類型昏兆,再次賦值的時(shí)候不需要帶類型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()方法來嘗試通過一個(gè)原始值來尋找他所對(duì)應(yīng)的枚舉成員
# possiblePlanet is of type Planet? and equals Planet.Uranus”
# possiblePlanet是一個(gè)Planet?類型妇穴,可能會(huì)是nil爬虱,因此需要判斷:
let positionToFind = 9
if let somePlanet = Planet.fromRaw(positionToFind) { #可選綁定
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 腾它,那么就會(huì)走到這
}
十六.類和結(jié)構(gòu)體
反饋一個(gè)問題:
binary operator === can not be applied
[swift語言詳解]http://c.biancheng.net/cpp/html/2427.html 在數(shù)組的===比較這一塊是錯(cuò)誤的跑筝,恒等用在引用類型上,而數(shù)組是值類型瞒滴,可以看下這個(gè)demo:
Paste_Image.png
[定義]
struct Resolution { #Resolution的結(jié)構(gòu)體曲梗,用來描述一個(gè)顯示器的像素分辨率
var width = 0
var heigth = 0
}
class VideoMode { #VideoMode的類,用來描述一個(gè)視頻顯示器的特定模式
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)
[屬性]
存儲(chǔ)屬性:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
延遲存儲(chǔ)屬性:
延遲存儲(chǔ)屬性是指當(dāng)?shù)谝淮伪徽{(diào)用的時(shí)候才會(huì)計(jì)算其初始值的屬性逛腿。在屬性聲明前使用@lazy來標(biāo)示一個(gè)延遲存儲(chǔ)屬性稀并。
必須將延遲存儲(chǔ)屬性聲明成變量(使用var關(guān)鍵字),因?yàn)閷傩缘闹翟趯?shí)例構(gòu)造完成之前可能無法得到单默。
class DataImporter {
/*
DataImporter 是一個(gè)將外部文件中的數(shù)據(jù)導(dǎo)入的類碘举。
這個(gè)類的初始化會(huì)消耗不少時(shí)間。
*/
var fileName = "data.txt"
// 這是提供數(shù)據(jù)導(dǎo)入功能
}
class DataManager {
@lazy var importer = DataImporter()
var data = String[]()
// 這是提供數(shù)據(jù)管理功能
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// DataImporter 實(shí)例的 importer 屬性還沒有被創(chuàng)建
DataManager的一個(gè)功能是從文件導(dǎo)入數(shù)據(jù)搁廓,該功能由DataImporter類提供引颈,DataImporter需要消耗不少時(shí)間完成初始化:因?yàn)樗膶?shí)例在初始化時(shí)可能要打開文件,還要讀取文件內(nèi)容到內(nèi)存境蜕。DataManager也可能不從文件中導(dǎo)入數(shù)據(jù)蝙场。所以當(dāng)DataManager的實(shí)例被創(chuàng)建時(shí),沒必要?jiǎng)?chuàng)建一個(gè)DataImporter的實(shí)例粱年,更明智的是當(dāng)用到DataImporter的時(shí)候才去創(chuàng)建它售滤。由于使用了@lazy,importer屬性只有在第一次被訪問的時(shí)候才被創(chuàng)建。比如訪問它的屬性fileName時(shí):
println(manager.importer.fileName)
// DataImporter 實(shí)例的 importer 屬性現(xiàn)在被創(chuàng)建了
// 輸出 "data.txt”
計(jì)算屬性:
類完箩、結(jié)構(gòu)體和枚舉可以定義計(jì)算屬性赐俗,計(jì)算屬性不直接存儲(chǔ)值,而是提供一個(gè) getter 來獲取值弊知,一個(gè)可選的 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) 可以省略不寫,用默認(rèn)的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)視器:
暫時(shí)不知道哪里用到秩彤,先不說了
類型屬性:
略