創建對象
OC:alloc initWith
Swift:(XXX:)
調用方法
OC:[uicolor redcolor]
Swift:uicolor.redcolor()
枚舉
OC:UIButtonTypeContactAdd
Swift:UIButtonType.ContactAdd
輸出
OC:NSLog(@"Hello, World!");
Swift:2.0開始:? print("Hello, World!")
注釋
* Swift的編譯器將會在編譯代碼時自動忽略掉注釋部分
*單行注釋//
*多行注釋/**/
與C語言多行注釋不同,Swift的多行注釋可以嵌套在其它的多行注釋之中嵌套多行注釋
*注釋嵌套/*/**/*/
常量變量
* let常量:常量的值一旦設定就不能改變
* var變量:變量的值可以隨意更改
*常量&變量的使用原則:
*為保證數據的安全性盡量先用let,只有需要改變的時候才使用var
常量定義格式
*聲明符號常量名稱:類型標注
* let number: Int
*特點:一旦設定就不能改變
定義變量格式
*聲明符號常量名稱:類型標注
* var number: Int
*特點:變量的值可以隨意更改
*注意:一般來說你很少需要寫類型標注。如果你在聲明常量或者變量的時候賦了一個初始值,Swift可以推斷出這個常量或者變量的類型
常量和變量的命名
*你可以用任何你喜歡的字符作為常量和變量名,包括Unicode字符
*常量與變量名不能包含數學符號,箭頭,保留的(或者非法的)Unicode碼位,連線與制表符
*也不能以數字開頭,但是可以在常量與變量名的其他地方包含數字
* ...和C和OC一樣, no zuo no die
注意:
*如果你需要使用與Swift保留關鍵字相同的名稱作為常量或者變量名,你可以使用反引號(`)將關鍵字包圍的方式將其作為名字使用。
*無論如何,你應當避免使用關鍵字作為常量或變量名,除非你別無選擇。
let??=?"狗"
let?`int` =?88
類型推斷
*編譯器可以在編譯代碼的時候自動推斷出表達式的類型。(其它語言是沒有類型推斷)
*原理很簡單,只要檢查你賦的值即可
*如果沒有指定表達式的類型,也沒有賦予初始值,編譯器會報錯(type annotation missing in pattern)
//:指定類型
let dValue: Double
dValue = 22.2
print(dValue)
//:不指定類型,利用類型推斷
let num = 10
print(num)
let value = 10.10
print(value)
元祖
*元組(tuples)把多個值組合成一個復合值
*將多個相同或者不同類型的值用一個小括號括起來就是一個元祖
*元組內的值可以是任意類型,并不要求是相同類型
*作為函數返回值時,元組非常有用
注意:
*元組在臨時組織值的時候很有用,但是并不適合創建復雜的數據結構。如果你的數據結構并不是臨時使用,請使用類或者結構體而不是元組
//定義元祖
let student = ("lnj", 30, 99.8)
//通過下標來訪問元組中的單個元素
print(student)
print(student.0)
print(student.1)
print(student.2)
//給單個元素命名
let student1 = (name:"lnj",age:30,score:99.8)
print(student1.name)
print(student1.age)
print(student1.score)
//元組的內容分解(decompose)
let (name , age , score) =? ("lnj", 30, 99.8)
print(name)
print(age)
print(score)
類型安全
* Swift是一個類型安全(type safe)的語言,它會在編譯你的代碼時進行類型檢查(type checks),并把不匹配的類型標記為錯誤。這可以讓你在開發的時候盡早發現并修復錯誤
* swift對數據類型要求異常嚴格, swift中任何時候,都不會做`隱式轉換`,如果要對不同類型的數據進行計算,必須顯示類型轉換
注意:
*結合數字類常量和變量不同于結合數字類字面量。字面量8可以直接和字面量3.1415926相加,因為數字字面量本身沒有明確的類型。它們的類型只在編譯器需要求值的時候被推測
* Double和CGFloat也需要轉換
let ii = 10
let jj = 10.1
//let sum = ii + jj //錯誤寫法
let sum = Double(ii) + jj
print(sum)
//注意:Double()并不會修改intValue的值,而是通過intValue的值生成一個臨時的值賦值給doubleValue
print(ii)
// Double和CGFloat也需要轉換
let size = CGSize(width: 10, height: 10)
let res = size.width + CGFloat(dValue)
流程控制結構
Swift提供了類似C語言的流程控制結構(if/switch/for/while/dowhile)
分支if
*只能以Bool作為條件語句
*條件語句不需要加()
* {}不能省略
* Swift中if分支的模式可以使用where語句來判斷額外的條件
*其它和OCif一樣
let intValue = 10
if intValue > 5{
print("OK")
}
let testValue: Int? = 10
if let d = testValue where testValue > 9
{
print("滿足")
}
Bool類型
* C語言和OC并沒有真正的Bool類型
* OC語言的Bool類型YES/NO是`typedef signed char BOOL;`非0即真
Swift引入了真正的Bool類型true/false
* Swift中沒有C和OC中非零即真的概念
* Swfit中邏輯值只有兩個true/false
*如果你在需要使用Bool類型的地方使用了非布爾值,Swift的類型安全機制會報錯
//if intValue = 10 { //可能將判斷寫錯, Swift有效的避免了這種情況
if intValue == 10 {
print(intValue)
}
三目運算符
*三目運算符的特殊在于它是有三個操作數的運算符,它簡潔地表達根據問題成立與否作出二選一的操作
*格式:問題?答案1 :答案2
提示:
* Swift中三目運算符用得很多
注意:
*過度使用三目運算符會使簡潔的代碼變的難懂。我們應避免在一個組合語句中使用多個三目運算符
let result = intValue > 20 ? 20 : 10
分支Switch
* OC中case后面必須加上break否則會貫穿, Swift不用
* Swift中如果想貫穿必須使用fallthrough
* OC中可以不寫default,Swift中只有滿足所有條件才能忽略default
* OC中default位置可以隨便放,Swift不可以
* OC中在case中定義變量需要加大括號,否則作用域混亂, Swift不用加大括號
* Swift中的switch可以判斷區間和元祖
* Swift中case分支的模式可以使用where語句來判斷額外的條件
注意:
Swift中每一個case分支都必須包含至少一條語句,不像C語言里的switch語句,在Swift中,switch語句不會同時匹配多個條件
var rank = "A"
switch rank{
//default:
//? ? print("沒有評級")
case "A", "B":
var num = 10
print("優")
fallthrough
case "C":
print("差")
default:
print("沒有評級")
}
匹配區間
*閉區間操作符...包含頭包含尾
*半開區間操作符..<包含頭不包含尾
var age1 = 10
switch age1 {
case 0:
print("0")
case 1..<18:
print("未成年")
case 18..<30:
print("成年")
default:
print("老年人")
}
//:匹配元祖
var point = (50, 50)
switch point{
//只有where后面的條件表達式為真才賦值并執行case后的語句
case (0, 0):
print("原點")
case (50, 50):
print("中點")
default:
print("Other")
}
//:值綁定(Value Bindings)
switch point{
//只有where后面的條件表達式為真才賦值并執行case后的語句
case var(x, y) where x > y:
print("\(x) > \(y)")
case var(x, y) where x < y:
print("\(x) < \(y)")
default:
print("Other")
}
可選類型
*可選類型表示變量可以有值,也可以沒有值
* C和Objective-C中并沒有可選類型這個概念
* Swift中只有可選類型才可以賦值為nil
*如果你聲明一個可選常量或者變量但是沒有賦值,它們會自動被設置為nil
*格式: Optional<類型>或在類型后面加上?號
可選類型的取值是一個枚舉
* None沒有值
* Some有值
*由于可選類型在Swift中隨處可見,所以系統做了一個語法糖,在類型后面加上?
注意:
* nil不能用于非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請把它們聲明成對應的可選類型。
* Swift的nil和Objective-C中的nil并不一樣。在Objective-C中,nil是一個指向不存在對象的指針,所以Objective-C只有對象類型才能被設置為nil(基本類型不行)。在Swift中,nil不是指針——它是一個確定的值,用來表示值缺失。任何類型的可選狀態都可以被設置為nil,不只是對象類型。
var doubleValue1: Optional = 10.10
var intValue1: Int? = 0
intValue1 = nil
強制解析(forced unwrapping)
let url = NSURL(string: "http://www.520it.com/")
//如果強制解析OptionalValue,但是OptionalValue中沒有值時會引發一個運行時錯誤
print(url!)
//需要考慮url是否有值
if url != nil{
let request = NSURLRequest(URL: url!)
}
可選綁定(optional binding)
*不需要考慮url是否有值,能進入{}一定有值
*不僅可以用來判斷可選類型中是否有值,同時可以將可選類型中的值賦給一個常量或者變量
*可選綁定可以用在if和while語句中
提示:
*在實際開發中,使用頻率很高
if let url3 = NSURL(string: "http://www.520it.com/"){
let request = NSURLRequest(URL: url3)
}
隱式解析可選類型(implicitly unwrapped optionals)
*有時候在程序架構中,第一次被賦值之后,可以確定一個可選類型_總會_有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因為可以確定它總會有值
*隱式解析可選類型,并不需要每次都使用解析來獲取可選值,一個隱式解析可選類型其實就是一個普通類型,但是可以被當做非可選類型來使用
*格式:將可選類型后面的?改為!
* let xmgButton: UIButton!
注意:
*如果一個變量之后可能變成nil的話請不要使用隱式解析可選類型。如果你需要在變量的生命周期中判斷是否是nil的話,請使用普通可選類型
let url3: NSURL? = NSURL(string: "http://www.520it.com/")
let url4: NSURL! = NSURL(string: "http://www.520it.com/")
print(url3!) //需要驚嘆號來獲取值
print(url4)? //不需要感嘆號
循環
for循環-傳統
* for后的圓括號可以省略
*只能以bool作為條件語句
*如果只有條指令for后面的大括號`不可以`省略
* for后面的三個參數都可以省略,如果省略循環保持語句,那么默認為真
for var i = 0; i < 10; i += 1
{
print(i)
}
for循環-Swift
*閉區間:包含區間內所有值a...b例如: 1...5
*半閉區間:包含頭不包含尾a..
//? 0~9之間
for i in 0..<10
{
print(i)
}
// 0~10
for i in 0...10
{
print(i)
}
忽略_
*不關心下標可以使用_忽略下標
*在Swift中_使用非常廣泛
for _ in 0...10
{
print("lnj")
}
while循環
//: while循環,每次在循環開始時計算條件是否符合
var n = 0
while n < 10
{
print(n)
n += 1
}
//: repeat-while,每次在循環結束時計算條件是否符合
var m = 0
repeat{
print(m)
m += 1
}while m < 10
數組(有序數據集)
* Swift的Array類型被橋接到Foundation的NSArray類。
*格式: [] / [Int]() / Array()
* let不可變數組
* var可變數組
注意:
*不需要改變集合的時候創建不可變集合是很好的實踐。如此Swift編譯器可以優化我們創建的集合。
//創建一個空數組
var arrayM5: [String] = []
var arrayM4 = [String]()
var arrayM6 = Array()
//創建一個帶有默認值的數組
let array1 = ["lnj", "lmj"]
let array2 = Array(count: 5, repeatedValue: 0)
//遍歷
for item in array1{
print(item)
}
//遍歷同時拿到索引
for (index, item) in array1.enumerate()
{
print("index = \(index), item \(item)")
}
//獲取元素
array1[0]
array1[1]
//添加元素
//不能像不可變數組中添加內容
//array1.append("why")
// let不可變對象, var可變對象
var arrayM = ["lnj", "lmj"]
arrayM.append("why")
//數組可以存放任意類型
var arrayM2 = ["lnj", "lmj", 123]
arrayM2.append("456")
//如果需要添加其它類型必須提前聲明為AnyObject
//arrayM.append(123)
//合并數組
var arrayM3 = ["zs", "ls", "ww", "zl"]
arrayM += arrayM3
//只有相同類型的數組才可以合并
//arrayM2 += arrayM3
print(arrayM.count)
//和區間搭配使用
arrayM += arrayM3[0...2]
print(arrayM.count)
//刪除
arrayM3.removeAtIndex(1)
arrayM3
//刪除所有
//arrayM3.removeAll()
//和區間搭配使用
//arrayM3.removeRange(Range(start: 0, end: 2))
arrayM3.removeRange(0..<2) //其實Range就是半閉區間
arrayM3
//刪除并保留容量
arrayM3.removeAll(keepCapacity: true)
arrayM3.capacity
arrayM3.append("1")
arrayM3.capacity
arrayM3.append("2")
arrayM3.capacity
arrayM3.append("3")
arrayM3.capacity
arrayM3.append("4")
arrayM3.capacity
arrayM3.append("5")
//超過容量,容量會直接*2
arrayM3.capacity
字典(無序數據集)
* Swift的Dictionary類型被橋接到Foundation的NSDictionary類。
*格式[:] / Dictionary
* let不可變字典
* var可變字典
注意:
*一個字典的Key類型必須遵循Hashable協議
//創建一個空字典
var dict3: [String: AnyObject]
dict3 = [:]
var dict4 = [String: AnyObject]()
//創建一個帶有默認值字典
var dict5 = ["name": "lnj", "age": 30]
//最常見的字典類型[String : AnyObject],例如JSON
var dict = ["name":"lnj", "age": 30]
//遍歷字典
// k,v可以隨便寫,前面是key后面是value
for (k, v) in dict{
print(k)
print(v)
}
//獲取元素
dict["name"]
//添加元素
//如果key不存在會新增
dict["gender"] = "man"
dict
//替換元素
//如果key存在會替換
dict["name"] = "why"
//刪除元素
dict.removeValueForKey("name")
dict
//合并字典
var dict2 = ["score": 123]
for (k, v) in dict2{
dict[k] = v
}
dict
字符串
* Swift的String類型與Foundation NSString類進行了無縫橋接
* OC語言中的字符串也是以\0結尾, Swift不是
* OC中字符串是一個對象, Swift中使用String是一個結構體,效率更高,支持遍歷
注意
* Swift的String類型是值類型。如果您創建了一個新的字符串,那么當其進行常量、變量賦值操作,或在函數/方法中傳遞時,會進行值拷貝。任何情況下,都會對已有字符串值創建新副本,并對該新副本進行傳遞或賦值操作
// Swift字符串不是以\0結尾
var stringValue = "abc\0bcd"
print(stringValue)
//遍歷字符串
var str = "南哥很帥"
for c in str.characters
{
print(c)
}
//連接字符串和字符
var str2 = "cool"
str2 += str
let myAge:Int? = 30
let myName = "lnj"
//字符串插值
//拼接字符串的時如果字符串是可選內心,要特別注意,會帶上Optional
let str3 = "name = \(myName), age = \(myAge!)"
//需要格式的時候,怎么辦00:00:00
let frmStr = String(format: "%02d:%02d:%02d", arguments: [9, 23, 8])
//字符串截取,建議使用NSString
let str4 = "xmgcool"
let nsStr: NSString = str4
let subStr = nsStr.substringWithRange(NSMakeRange(0, 3))
//使用startIndex屬性可以獲取一個String的第一個Character的索引
//使用endIndex屬性可以獲取最后一個Character的后一個位置的索引
let subStr2 = str4.substringToIndex(str4.startIndex.advancedBy(3))
let range = Range(start: str4.startIndex, end: str4.startIndex.advancedBy(3))
let subStr3 = str4.substringWithRange(range)
函數:
*函數是用來完成特定任務的獨立的代碼塊。你給一個函數起一個合適的名字,用來標識函數做什么,并且當函數需要執行的時候,這個名字會被用于“調用”函數
*格式:
* func函數名稱(參數名:參數類型,參數名:參數類型...) ->函數返回值{函數實現部分}
沒有參數沒有返回值
1.可以寫為->Void
2.可以寫為->()
3.可以省略
* Void。它其實是一個空的元組(tuple),沒有任何元素,可以寫成()
func say() -> Void{
print("lnj")
}
say()
func say2() -> (){
print("lnj")
}
say2()
func say3(){
print("lnj")
}
say3()
有參數沒有返回值
內部/外部參數
*內部參數: Swift2.0以前,默認情況下的參數都是內部參數
*? ? ? ? ? Swift2.0開始,默認將第二個參數名稱作為外部參數
*外部參數只能外部用,函數內部不能使用,函數內部只能使用內部參數
*忽略外部參數:在內部參數前加_
func sum(a: Int, b: Int){
print(a + b)
}
sum(10, b: 20)
func summ(a: Int, _ b: Int){
print(a + b)
}
summ(10, 20)
// xy外部參數, ab內部參數
// Swift2.0以前可以寫#
func sum2(x a: Int, y b: Int){
print(a + b)
}
sum2(x: 10, y: 20)
默認參數(Default Parameter Values)
*格式: func method(parameter: Int = 0){}
*當默認值被定義后,調用這個函數時可以忽略這個參數
*其它語言的默認參數必須寫在最后面, Swift可以寫在任意位置
注意
*將帶有默認值的參數放在函數參數列表的最后。這樣可以保證在函數調用時,非默認參數的順序是一致的,同時使得相同的函數在不同情況下調用時顯得更為清晰。
func joinString(s1:String , jioner:String = "??",toString s2:String) ->String
{
return s1 + jioner + s2;
}
joinString("lnj", jioner: "和", toString: "xmg")
joinString("lnj", toString: "xmg")
常量參數和變量參數(Constant and Variable Parameters)
*函數參數默認是常量,在函數內部不能修改
*如果想在函數中修改參數,必須在參數前加上var
注意
*對變量參數所進行的修改在函數調用結束后便消失了,并且對于函數體外是不可見的。變量參數僅僅存在于函數調用的生命周期中
func swap(var a:Int, var b:Int)
{
print("交換前a = \(a) b = \(b)")
let temp = a;
a = b;? //可以修改,但不會影響實參
b = temp;
print("交換后a = \(a) b = \(b)")
}
var x = 10
var y = 20
print("交換前a = \(x) b = \(y)")
swap(x, b: y)
print("交換后a = \(x) b = \(y)")
輸入輸出參數(In-Out Parameters)
*變量參數,正如上面所述,僅僅能在函數體內被更改。如果你想要一個函數可以修改參數的值,并且想要在這些修改在函數調用結束后仍然存在,那么就應該把這個參數定義為輸入輸出參數(In-Out Parameters)
*定義一個輸入輸出參數時,在參數定義前加inout關鍵字
注意
*輸入輸出參數不能有默認值,而且可變參數不能用inout標記。如果你用inout標記一個參數,這個參數不能被var或者let標記。
func swap2(inout a:Int, inout b:Int)
{
let temp = a;
a = b;
b = temp;
}
var x1 = 10;
var y1 = 20;
print("交換前a = \(x1) b = \(y1)")
swap2(&x1, b: &y1)
print("交換后a = \(x1) b = \(y1)")
可變參數(Variadic Parameters)
*一個可變參數可以接收零個或多個值
*如果沒有變參函數,并且函數的參數個數又不確定那么只能寫多個方法或者用將函數參數改為集合
*格式func method(parameter: Int...){}
*可變參數在函數中可以當做一個數組
注意
*一個函數最多只能有一個可變參數
*變參只能是同種類型的數據
*變參必須指定數據類型
*如果函數有一個或多個帶默認值的參數,而且還有一個可變參數,那么把可變參數放在參數表的最后
func add(nums:Int..., other:Int) -> Int
{
var sum = 0;
for num in nums
{
sum += num
}
return sum + other
}
print(add(1, 2, 3, other: 9))//會將99傳遞給第一個參數,后面的傳遞給nums
//沒有參數有返回值
func getNumer() ->Int{
return 998
}
print(getNumer())
//有參數有返回值
func sum3(a: Int, b: Int) ->Int{
return a + b
}
print(sum3(10, b: 20))
//嵌套函數
func showArray(array:[Int])
{
//嵌套函數
func printArray(arr:[Int])
{
for number in array
{
print("\(number), ")
}
}
printArray(array)
}
showArray([1, 3, 5, 7, 9])
函數類型(Function Types)
*函數類型作為參數類型(Function Types as Parameter Types)
*函數類型作為返回類型(Function Types as Return Types)
*嵌套函數(Nested Functions)
提前退出
*像if語句一樣,guard的執行取決于一個表達式的布爾值。我們可以使用guard語句來要求條件必須為真時,以執行guard語句后的代碼。
*如果guard語句的條件被滿足,則在保護語句的封閉大括號結束后繼續執行代碼
*任何使用了可選綁定作為條件的一部分并被分配了值的變量或常量對于剩下的保護語句出現的代碼段是可用的
*如果條件不被滿足,在else分支上的代碼就會被執行。
* else這個分支必須轉移控制以退出guard語句出現的代碼段。它可以用控制轉移語句如return,break,continue或者throw做這件事
func divide3(dividend: Double?, divisor: Double?) -> Double? {
guard let dividend = dividend else {
return .None
}
guard let divisor = divisor else {
return .None
}
guard divisor != 0 else {
return .None
}
return dividend / divisor
}
print(divide3(10, divisor: 20))