swift3學習基礎教程摘要:
1、OC中nil是指向一個不存在對象的指針。swift中表示任何值的缺省。 2、條件判斷的時候,可選行不能為nil;條件不能為false。這樣才成立:
if let f = Int("4"),let s = Int("42"), f < s && s < 100 {print(f)}
3、如果想判斷一個非可選型(沒有?聲明)變量是否為nil。那么就可以把這個聲明為隱式解析可選類型(帶!)。這時候就可以對變量進行是否為nil判斷了。
var assumedStr:String! = "xxx"if assumedStr != nil {assumedStr.appendContentsOf("xx")}
4、函數可以通過在聲明中添加throws關鍵字拋出錯誤信息:(錯誤處理)
do {try canThrowAnError()}catch{}func canThrowAnError() throws { }
5、斷言,主要用于調試使用:觸發斷言會終止應用繼續執行:
let a = -1assert(a>=0,"error")
6、 swift中賦值不會返回任何值,所以就避免了oc里有人在if條件里把’==’寫成’=’; swift中的’+’可以對字符串進行操作:”hello”+”world” = “helloworld”; swift沒有了’++’、’–’運算符,用’+=’、’-=’代替,但是有一個需要注意:’a+=1’其實是’a=a+1’的簡寫,而賦值運算符’=’是沒有返回值的,所以swift中’let b = a += 1’是錯誤的,’a=a+1’沒有返回值,即不會給b賦值; swift中比較運算,元組也可以進行比較,當然Bool值是不允許比較的,所以帶Bool值的元組不可以進行比較,元組的比較也是逐個元素進行比較的; swift中空合運算符’??’是專門針對可選型的三目運算符,’a ?? b’是’a != nil ? a! : b’ 的簡寫,但是有一點需要非常清楚,a一定要是可選型,不然這個運算符就沒有意義了,因為理論上非可選型的值是永遠不會為nil的,也就沒有這種判斷的必要了。 swift還有一個坑需要說明一下的就是’|’運算符。我們在OC里經常會用到這個運算符,尤其是枚舉類型的時候,比如設置navigationBar的樣式。swift是沒有這個運算符的,但是在需要用到多個值修飾的時候,直接使用’[]’就好了: self.navigationController!.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor(),..] 7、swift數組,兩個數組相加創建一個新的數組,但是這兩個數組類型必須得一樣;swift多了一個Set集合類型; 8、 swift3 for循環只能使用for in; 新的repeat..while和do..while 作用是一樣的,且swift3沒有了do..while; swift3中,switch中case不需要顯示地使用break跳出,但是每個case都必須有一條語句,否則就是無效的。所以case也可以同時滿足多個條件(復合匹配),每個條件用逗號隔開;case里也可以是元組,這個時候就可以表示點、面積了:
let point = (1,1)switch point {case (0,0):print("原點")case (_,0):print("x軸")case (0,_):print("y軸")case (-2...2,-2...2):print("在[4*4]的面積里")default:print("\(point)")}
case里也可以進行值綁定,將匹配的值綁定到一個臨時的常量或者變量里,在case分支內就可以對其進行操作:
let anotherPoint = (2,0)switch anotherPoint {case (var x, 0):x += 2print("x軸:\(x)")case (0, var y):print("y軸:\(y)")default:print("\(point)")}print("\(point)")
case里的判斷也可以使用where進行一些額外的條件判斷:
let yetAntherPoint = (1,-1)switch yetAntherPoint {case let(x,y) where x == y:print("在x==y的分角線上")case let(x,y) where x == -y:print("在x==-y的分角線上")default:print("\(point)")}
switch中case不需要使用break讓它跳出case,但是也可能需要執行下一個case的情況。所以新的關鍵字:fallthrough就是用來處理這種情況的; swift中除了if條件判斷外,新的guard也是條件判斷,guard語句總是帶一個else從句。如果條件為false則執行else里的語句,為true則跳過執行后續語句 9、檢測API可用性:后面那個*是必須的
if #available(iOS 10, *) {print("可用")}
10、多重返回值函數:返回值可以是可選型
func minMax(array:[Int])->(min:Int,max:Int)? {if array.isEmpty {return nil}var currentMin = array[0]var currentMax = array[0]for value in array[1..<array.count] {if value < currentMin {currentMin = value}else if value > currentMax {currentMax = value}}return (currentMin,currentMax)
}
if let bounts = minMax(array: [9,-2,1,3,1000,29,-12]) {print("min:\(bounts.min),max:\(bounts.max)")
}
11、可變參數函數:可變參數的傳入值在函數中為此類型的一個數組,一個函數最多只有一個可變參數:
func averageNum(_ numbers:Double...)->Double {var total:Double = 0for number in numbers {total += number}return total/Double(numbers.count)
}print("\(averageNum(1,2,3,4,5))")
12、輸入輸出參數:是指傳入的參數在函數體內被修改了,修改后的結果在函數體外仍有效果,注意傳入的參數必須是var類型的,函數形參用inout關鍵字修飾:
var someInt = 3
var antherInt = 107func swapTwoInts(_ a: inout Int,_ b: inout Int) -> Int{let temparam = aa = bb = temparamreturn a+b
}
let result = swapTwoInts(&someInt, &antherInt)
print("\(result),\(someInt),\(antherInt)")
13、函數類型:像其他基礎類型一樣的類型,如普通參數一樣使用:
func add(_ a:Int,_ b:Int) -> Int {return a + b
}var mathFunc:(Int,Int)->Int = add
print("\(mathFunc(1,2))")
//mathFunc的類型就是:(Int,Int)->Int.
函數類型作為參數:
func printMathFunc(_ mathFunc1:(Int,Int)->Int,_ a:Int,_ b:Int){print("\(mathFunc1(a,b))")
}
printMathFunc(add, 3, 4)
函數類型作為返回值:
func stepForward(_ input:Int)->Int{return input+1
}
func stepBackward(_ input:Int)->Int{return input-1
}
func chooseStepFunc(back:Bool) -> (Int) -> Int {return back ? stepBackward : stepForward
}
14、嵌套函數:即函數里面嵌套函數:
func chooseStepFunc2(back:Bool) -> (Int) -> Int {func stepForward2(_ input:Int)->Int{return input+1}func stepBackward2(_ input:Int)->Int{return input-1}return back ? stepBackward2 : stepForward2
}
15、閉包http://blog.csdn.net/u012297622/article/details/51533130 16、枚舉:
enum CompassPoint {case northcase southcase eastcase west
}
swift的枚舉成員與OC不同,創建時不會被賦予一個默認的整型值。CompassPoint的成員的類型就是CompassPoint類型,枚舉成員本身就是完備的值。但是它們也有隱式原始值,當使用字符串作為枚舉類型的原始值,每個枚舉成員的隱式原始值為該枚舉成員的名稱: CompassPoint.west.rawValue 值為 “west” 17、結構體是值類型,類是引用類型。將一個結構體聲明為一個常量,則結構體里的屬性都是常量;將一個類聲明為常量,類的屬性不會都成為常量,而是保持原來的存儲屬性。 lazy延遲屬性:必須是變量,因為屬性的初始值可能在實例構造完成之后才會得到。而常量屬性在構造過程完成前必須要有初始值,因此無法聲明成延遲屬性。 計算屬性:是提供了getter和一個可選的setter的屬性。setter可以使用默認的newValue。計算屬性必須用var定義。 屬性觀察器:每次屬性被設置值的時候都會調用屬性觀察器:willSet、didSet static:在class里也可以用class關鍵字代替,其實就相當于類方法一樣的效果。 18、mutating:實例方法中修改值類型(主要是結構體和枚舉),因為默認情況下,值類型的屬性不能在它的實例方法中被修改;給隱含的self賦值:
struct Point {var x = 0.0,y = 0.0mutating func moveBy(x:Double,y:Double){self.x += xself.y += y}
}
var somePoint = Point(x:1.0,y:1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("point:\(somePoint.x),\(somePoint.y)")
enum TriStateSwitch {case off,low,highmutating func next() {switch self {case .off:self = .lowcase .low:self = .highcase .high:self = .off}}
}
var overLight = TriStateSwitch.low
overLight.next()
overLight.next()
19、類型方法:在func關鍵字前面加上static,來指定類方法。類還可以用關鍵字class來允許子類重寫父類的方法實現:
struct LevelTracher {static var high = 1var current = 1static func unlock(_ level:Int){if level > high {high = level}}static func isUnlocked(_ level:Int)->Bool{return level<=high}@discardableResult //可以忽略返回值mutating func advance(to level:Int)->Bool{if LevelTracher.isUnlocked(level) {current = levelreturn true}else{return false}}
}
20、下標語法:下標定義使用subscript關鍵字,它通過指定一個或多個輸入參數和返回類型;與實例方法不同的是下標可以設定為只讀或讀寫。分別由getter和setter實現,同樣setter有一個參數newValue,當然也可以不指定參數,它就會有一個默認的newValue,而如果是只讀的話,get關鍵字也是可以省略的:
struct TimesTable{var multipliter:Intsubscript(index:Int)->Int{return multipliter * index}subscript(index:Int,index2:Int)->Int{get{return multipliter * index * index2}set{print("newValue:\(newValue)")multipliter = newValue}}
}var m = TimesTable(multipliter: 2)
m[0]
m[1,2]
m[0,1] = 6
21、繼承: 可以將繼承來的只讀屬性重寫成讀寫屬性,提供getter和setter。但是,不可以將繼承來的讀寫屬性重寫為一個只讀屬性; 不可以為繼承來的常量存儲型屬性或繼承來的只讀計算型屬性添加屬性觀察器。因為這些值是不可以被設置的; 此外,不可以同時提供重寫的setter和重寫的屬性觀察器; 防止重寫,可以通過把方法、屬性或下標標記為final來防治被重寫,被final標記了的class是不可以被繼承的。 22、為存儲型屬性設置默認值或在構造器中賦值時,它們的值是被直接設置的,不會觸發任何屬性觀察器。構造過程可以給常量復制,一旦構造過程結束,那么它將不可被修改。結構體有逐一成員構造器。 23、引用計數:每一次賦值,引用計數加一:
class Person {let name:Stringinit(name:String) {self.name = nameprint("\(name) is being initialized")}deinit {print("\(name) is being deinitialized")}
}var refrence1:Person?
var refrence2:Person?
var refrence3:Person?
//當創建一個類的新實例的時候,ARC會分配一塊內存來存儲該實例信息
refrence1 = Person(name: "John") //引用計數1
refrence2 = refrence1 //引用計數2
refrence3 = refrence1 //引用計數3
refrence1 = nil //引用計數2
refrence2 = nil //引用計數1
refrence3 = nil //引用計數0 釋放內存
實例間的循環強引用:
class Person {let name:Stringinit(name:String) {self.name = name}var apartment:Apartment?deinit {print("\(name) is being deinitialized")}
}
class Apartment{let unit:Stringinit(unit:String) {var tenant:Person?deinit {print("Apartment\(unit) is being deinitialized")}
}
//這樣賦值之后,產生循環強引用。
var john = Person(name: "John")
var unit4 = Apartment(unit: "4A")
john.apartment = unit4
unit4.tenant = john
解決實例之間的循環強引用——用無主引用和弱引用:相互之間的兩個屬性的值都允許為nil,并會潛在的產生循環強引用。這種場景最適合弱引用來解決;而一個屬性的值允許為nil,而另一個屬性的值不允許為nil,這也可能產生循環強引用。這種場景最適合無主引用來解決。
//弱引用
class Apartment{let unit:Stringinit(unit:String) {weak var tenant:Person? //注意這里的Person和Apartment都是可選性的。deinit {print("Apartment\(unit) is being deinitialized")}
}
然而還有一種場景,兩個屬性都必須有值,并且初始化后永遠不會為nil。這種場景下,需要一個類使用無主屬性,另外一個類使用隱式解析可選屬性。 24、可選型:訪問可選類型下標?是在[]之前:test[“dave”]?[0] 25、錯誤處理:在返回箭頭->前添加throws關鍵字表示該函數、方法或構造器可以拋出錯誤,并將錯誤傳遞到函數被調用時的作用域,并且可以一直傳下去。但是在每個調用的位置前添加try關鍵字。然后在最后用do-catch處理:
enum VendingMachineError:Error {case invalidSelection //選擇無效case insufficientFunds(coinsNeeded:Int) //金額不足case outofStock //缺貨
}
struct Item{var price:Intvar count:Int
}class VendingMachine{var inventory = ["Candy Bar":Item(price: 12, count: 7),"Chips":Item(price: 10, count: 4),"Pretzels":Item(price: 7, count: 11)]var coinsDeposited = 0func dispenseSnack(snack:String){print("Dispensing \(snack)")}func vend(itemNames name:String) throws {guard let item = inventory[name] else {throw VendingMachineError.invalidSelection}guard item.count > 0 else {throw VendingMachineError.outofStock}guard item.price <= coinsDeposited else {throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)}coinsDeposited -= item.pricevar newItem = itemnewItem.count -= 1inventory[name] = newItemprint("Dispensing \(name)")}
}
let favoriteSnacks = ["Alice":"Chips","Bob":"Licorice","Eve":"Pretzels",
]
func buyFavoriteSnack(person:String,vendingMachine:VendingMachine) throws {let snackName = favoriteSnacks[person] ?? "Candy Bar"try vendingMachine.vend(itemNames: snackName)
}var vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
do {try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
} catch VendingMachineError.invalidSelection {print("invalidSelection")
} catch VendingMachineError.outofStock {print("outofStock")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {print("\(coinsNeeded) coins")
}
可用try?通過錯誤轉換成一個可選值來處理錯誤。可用try!來禁止錯誤傳遞。 指定清理操作:defer語句是在即將離開當前代碼塊時執行一系列語句。
let file = open(f)
defer {close()
}
26、類型轉換:類型檢查用(is)來檢查一個實例是否屬于特定子類型;可以用類型轉換符(as? 或 as! )向下轉型; 兩個特殊的不確定類型: . Any : 可以表示任何類型,包括函數類型 . AnyObject : 可以表示任何類類型的實例
var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.1415926)
things.append("hello")
things.append((3.0, 5.0))
things.append(Person(name: "fcf"))
things.append({(name:String)->String in "hello"})for thing in things {switch thing {case 0 as Int:print("zero as an Int")case 0 as Double:print("zero as a Double")case let someInt as Int:print("an integer value of \(someInt)")case let someDouble as Double where someDouble > 0 :print("a positive double value of \(someDouble)")case is Double:print("aome other double")case let someString as String:print("a string value of \(someString)")case let (x,y) as (Double,Double):print("an (x,y) point at (\(x),\(y))")case let person as Person:print("an person name is \(person.name)")case let stringConverter as (String) -> String:print(stringConverter("Michael"))default:print("something else")}
}
27、擴展extension: 用extension關鍵字聲明,可以為類添加新的方法、屬性、下標、嵌套類型等。甚至可以用擴展添加協議,例如:
extension Person:UITabBarDelegate{
}
28、協議protocol: 協議要求在需要和OC打交道的代碼中,協議和可選都要求必須帶@objc屬性。 29、泛性:
func swapTwoValues<F>(_ a: inout F, _ b: inout F){let temporaryA = aa = bb = temporaryA
}var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
print("\(someInt),\(anotherInt)")
泛型類型:
struct Strack<FCF>{var items = [FCF]()mutating func push(item:FCF){items.append(item)}mutating func pop()->FCF {return items.removeLast()}
}
var stackOfStrings = Strack<String>()
stackOfStrings.push(item: "f")
stackOfStrings.push(item: "c")
stackOfStrings.push(item: "e")
print("\(stackOfStrings.pop())")
擴展泛型類型:
//擴展泛型類型
extension Strack{var topItem:FCF? {return items.isEmpty ? nil : items[items.count - 1]}
}
print(stackOfStrings.topItem ?? "")
類型約束:
//因為不是所有的類型都可以用==判斷相等,所以必須約束泛型是符合Equatable協議的類型。因為所有任何遵循該協議的類型必須實現==和!=。
func findIndex<F:Equatable>(_ valueToFind: F, in array:[F])->Int?{for (index, value) in array.enumerated() {if value == valueToFind {return index}}return nil
}
關聯類型:
protocol Container{associatedtype ItemTypemutating func append(item:ItemType)var count:Int{get}subscript(i:Int)->ItemType{get}
}
struct IntStrack:Container{var items = [Int]()mutating func push(item:Int){items.append(item)}mutating func pop()->Int{return items.removeLast()}typealias ItemType = Intmutating func append(item: IntStrack.ItemType) {self.push(item: item)}var count: Int{return items.count}subscript(i:Int)->Int{return items[i]}
}
通過where子句為關聯類型定義約束:
func allItemMatch<C1:Container,C2:Container>(_ someContainer:C1,_ anotherContainer:C2) -> Bool where C1.ItemType == C2.ItemType,C1.ItemType:Equatable{if someContainer.count != anotherContainer.count {return false}for i in 0..<someContainer.count {if someContainer[i] != anotherContainer[i] {return false}}return true
}
30、訪問控制: open: public: internal: filepart: private:
總結
以上是生活随笔 為你收集整理的swift3 语法摘要 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。