swift學習筆記《2》-swift語法

ytmaylover發表於2018-09-05

1.常量變數

  • let var

2.資料型別

  • 整型,浮點型,物件型別,結構體型別(swift中大部分類改為了結構體)
  • 整型
  • Int8 有符號8位整型

  • Int16 有符號16位整型

  • Int 32 有符號32位整型

  • Int 64 有符號64位整型

  • Int 與平臺有關,預設相當於OC中NSInteger

  • UInt8 無符號8位整型

  • UInt16,UInt32,UInt64

  • 浮點型

  • Float 32位浮點型 Double 64位浮點型

  • 基本運算

  • 相同運算子之間才能參與運算,因為swift中沒有隱式轉換

3.邏輯分支

  • if switch 三目運算子 等判斷語句

  • guard運算子(守護)

  • 當條件表示式位true的時候跳過else語句,繼續向下執行

  • 當條件表示式為false的時候進入else語句中,break,continue,return,throw等跳出

    guard 條件表示式 else {
        // 條換語句
        break
    }
    語句組
    
    複製程式碼
  • switch語句

  • switch 的case之後不必須加break case不在只是Int,可以是浮點,字串,區間(0..<10,0...10)

  • 一個case 可以判斷多個值,用,隔開

4.迴圈

  • for迴圈
  • 開區間(0..<10),閉區間(0...10)
  • for迴圈列印字典時可以使用元組
  • whiledo-while 迴圈
  • 使用repeat while迴圈代替do-while迴圈
  • i++已經被棄用,使用i=i+1;

5.字串

  • String 是結構體,效能比NSString 高

  • String的長度,astring.characters.count 字串長度

  • str1 + str2 兩個字串相加

  • 字串的格式化輸出

    String(format: "%02d:%02d", arguments: [min, second])
    複製程式碼
  • 字串的擷取 暫時先轉為NSString 進行擷取

    let myStr = "www.520it.com"
    var subStr = (myStr as NSString).substringFromIndex(4)
    subStr = (myStr as NSString).substringToIndex(3)
    subStr = (myStr as NSString).substringWithRange(NSRange(location: 4, length: 5))
    複製程式碼

6陣列

  • Array 一個範型陣列

  • 陣列宣告方法

    var stuArray1:Array<String>
    var stuArray2: [String]
    複製程式碼
  • 陣列的 增- 刪- 改- 查

    // 新增資料
    array.append("yz")
    // 刪除元素
    array.removeFirst()
    // 修改元素
    array[0] = "why"
    // 取值
    array[1]
    複製程式碼
  • 陣列的合併 同型別的兩個陣列可以直接相加

    // 陣列合並
    // 注意:只有相同型別的陣列才能合併
    var array = ["why", "lmj","lnj"]
    var array1 = ["yz", "wsz"]
    var array2 = array + array1;
    
    // 不建議一個陣列中存放多種型別的資料
    var array3 = [2, 3, "why"]
    var array4 = ["yz", 23]
    array3 + array4
    
    複製程式碼

7.字典

  • Dictionary 是個範型集合

  • 宣告方式

    var dict1: Dictionary<Int, String>
    var dict2: [Int: String]
    複製程式碼
  • 字典的增 -刪- 改- 查

    // 新增資料
    dict["height"] = 1.88
    dict["weight"] = 70.0
    // 刪除欄位
    dict.removeValueForKey("height")
    // 修改字典
    dict["name"] = "lmj"
    // 查詢字典
    dict["name"]
    複製程式碼
  • 字典的遍歷 使用元組

  • 字典的合併

    // 字典的合併
    var dict1 = ["name" : "yz", "age" : 20]
    var dict2 = ["height" : 1.87, "phoneNum" : "+86 110"]
    // 字典不可以相加合併
    for (key, value) in dict1 {
        dict2[key] = value
    }
    
    複製程式碼

8.元組

  • 是swift中特有的定義一組資料,型別可相同可不相同
    // 元組:HTTP錯誤
    // let array = [404, "Not Found"]
    // 寫法一:
    let error = (404, "Not Found")
    print(error.0)
    print(error.1)
    
    // 寫法二:
    
    let error = (errorCode : 404, errorInfo : "Not Found")
    print(error.errorCode)
    print(error.errorInfo)
    
    // 寫法三:
    let (errorCode, errorIno) = (404, "Not Found")
    print(errorCode)
    print(errorIno)
    複製程式碼

9.可選型別

  • 可選型別的取值,有值或者是空值

  • 可選型別的使用

  • 使用場景

    // 該方式利用型別推導
    let url = NSURL(string: "www.520it.com")
    // 通過url來建立request物件:在使用可選型別前要先進行判斷是否有值
    // 該語法成為可選繫結(如果url有值就解包賦值給tempURL,並且執行{})
    if let tempUrl = url {
        let request = NSURLRequest(URL: tempUrl)
    }
    複製程式碼

10.函式

  • 函式的格式

    func 函式名(引數列表) -> 返回值型別 {
        程式碼塊
        return 返回值
    }
    
    func 函式名(引數1:引數1型別,引數2:引數2型別) -> 返回值型別 {
        程式碼塊
        return 返回值
    }
    
    複製程式碼
  • 函式 外部引數和內部引數

  • 變數名前加標籤就是外部引數

  • 方法重寫 子類重新呼叫父類方法是重寫,override

  • 方法過載 方法名相同但是引數不同,稱為方法過載

    // num1和a是外部引數的名稱
    func ride(num1 num1 : Int, a num2 : Int, b num3 : Int) -> Int {
        return num1 * num2 * num3
    }
    
    var result1 = ride(num1: 20, a: 4, b: 5)
    // 方法的過載:方法名稱相同,但是引數不同,可以稱之為方法的過載(瞭解)
    func ride(num1: Int, _ num2 :Int) -> Int {
        return num1 * num2
    }
    var result2 = ride(20, 20)
    複製程式碼
  • 函式的預設引數

  • 不傳的話有個預設值

    func makecoffee(type :String = "卡布奇諾") -> String {
        return "製作一杯\(type)咖啡。"
    }
    複製程式碼
  • 可變引數

  • 可以接受不確定數量的輸入型別引數,但必須是相同型別,在引數型別後面拼接**...** 來實現

    func sum(numbers:Double...) -> Double {
        var total: Double = 0
        for number in numbers {
            total += number
        }
        return total
    }
    sum(100.0, 20, 30)
    sum(30, 80)
    複製程式碼
  • 函式引用型別-指標傳遞

  • 預設是值傳遞,不改變外部變數的值,如果想改變,需要傳地址

  • 傳入的地址必須是變數

  • swift提供inout 關鍵字實現

11.swift中類的使用

  • 定義類的時候可以沒有父類,需要父類的話大多可以使用NSObject 作為父類,非OC的NSObject

  • 類的屬性 分為 儲值屬性,算值屬性,類屬性

  • 儲值屬性

  • 計算型屬性 不儲存實際值,提供getter 和可選的setter間接獲取或設定其他屬性,

    • 一般只提供getter 方法,如果只實現了getter 方法,則為只讀屬性,可以省略get{},直接return
  • 類屬性 所有的類和類的例項都有一份類屬性,如果在某一處更新後,該類屬性就會被修改

  • 類屬性使用static 關鍵字修改,

  • 監聽屬性的修改

  • 在oc中使用set 方法監聽

  • 在swift中,使用屬性觀察者監聽和相應屬性值的變化

  • 使用屬性的will set 方法監測新值,在didset中監測舊值

  • willSet (new){ } didSet(old){}

  • 在didset中生成計算型屬性的值

  • didSet 屬性直接賦值不會呼叫didSet方法,而是在初始化之後再賦值才能呼叫

    var expires_in: NSTimeInterval = 0 {
        didSet {
            expiresDate = NSDate(timeIntervalSinceNow: expires_in)
        }
    }
    複製程式碼

12.類的建構函式

  • 建構函式的基本使用

  • 類的屬性必須有值,如果不是在初始化的時候複製,在構造方法中給類屬性賦值,

    class Person: NSObject {
        var name : String
        var age : Int
        // 重寫了NSObject(父類)的構造方法
        override init() {
            name = ""
            age = 0
        }
    }
    
    // 建立一個Person物件
    let p = Person()
    複製程式碼
  • 初始化的時候給屬性賦值

  • 如果在自定義物件的時候給屬性賦值,自定義init方法,會覆蓋init方法,不會有預設的初始化方法

    class Person: NSObject {
        var name : String
        var age : Int
        // 自定義建構函式,會覆蓋init()函式
        init(name : String, age : Int) {
            self.name = name
            self.age = age
        }
    }
    // 建立一個Person物件
    let p = Person(name: "why", age: 18)
    複製程式碼

13 字典轉模型 (初始化時傳入字典)

  • 字典取值是NSObject 是任意型別
  • 可以通過as轉換之後再賦值,不同型別不能直接賦值
    class Person: NSObject {
        var name : String
        var age : Int
        // 自定義建構函式,會覆蓋init()函式
        init(dict : [String : NSObject]) {
            name = dict["name"] as! String
            age = dict["age"] as! Int
        }
    }
    
    // 建立一個Person物件
    let dict = ["name" : "why", "age" : 18]
    let p = Person(dict: dict)
    複製程式碼

14 字典轉模型 (KVC 轉化)

  • kvc 不能保證全部複製,所以屬性要有預設值,基本資料型別預設值是0,物件結構體定義為可選即可
    class Person: NSObject {
        // 結構體或者類的型別,必須是可選型別.因為不能保證一定會賦值
        var name : String?
        // 基本資料型別不能是可選型別,否則KVC無法轉化
        var age : Int = 0
        
        // 自定義建構函式,會覆蓋init()函式
        init(dict : [String : NSObject]) {
            // 必須先初始化物件
            super.init()
            // 呼叫物件的KVC方法字典轉模型
            setValuesForKeysWithDictionary(dict)
        }
    }
    // 建立一個Person物件
    let dict = ["name" : "why", "age" : 18]
    let p = Person(dict: dict)
    複製程式碼

15閉包的介紹

  • 閉包就是匿名函式

  • block 的寫法

    型別:
    返回值(^block的名稱)(block的引數列表)
    ------
    
    值:
    ^(引數列表){
        // 執行的程式碼
    }
    複製程式碼
  • swift的寫法

  • 定義網路請求的類

    func loadRequest(callBack:()->()){
        callBack()
    }
    複製程式碼
  • 使用閉包

    httpTool.loadRequest( { ( )->( ) in 
        tableView.reloadData
    })
    複製程式碼
  • 閉包總結

    閉包的寫法:
    型別:  (型參列表)->( 返回值 )
    
    值:
    {  ( 型參列表 ) -> 返回值型別 in  
    
    // 執行程式碼
    }
    
    複製程式碼
  • 尾隨閉包

    • 如果閉包沒有引數沒有返回值,( ) -> ( ) in可以省略

    • 如果閉包是作為函式的最後一個引數,則可以將閉包寫在()後面

    • 如果函式只有一個引數,且最後一個引數是閉包,那麼()也可以不寫,直接在方法名後面拼接{}

      省略前
      httpTool.loadRequest({ ( ) -> ( ) in 
          print(完全不省略)
      })
      
      省略1
      httpTool.loadRequest({
          print(省略括號 in)
      })
      
      省略2
      httpTool.loadRequest( ){ 
          print(小括號前置)
      }
      
      省略3
      httpTool.loadRequest{ 
          print(終結版尾隨閉包)
      }
      複製程式碼

16.閉包的迴圈引用

  • deinit{}實現deinit 函式,檢測一個物件是否銷燬

  • swift 迴圈引用的三種方式

    • 使用weak,使用【weak self】,使用unowned 關鍵字
  • 使用weak 關鍵字對控制器持有,weakself是可選型別,使用時強行解包,因為一定有值

    weak var weakSelf = self
    httpTool.loadData {
        print("載入資料完成,更新介面:", NSThread.currentThread())
        weakSelf!.view.backgroundColor = UIColor.redColor()
    }
    
    複製程式碼
  • 使用 【weak self】 【weak self 】寫在閉包中,在閉包中使用的self 都是weak的

    httpTool.loadData {[weak self] () -> () in
        print("載入資料完成,更新介面:", NSThread.currentThread())
        self!.view.backgroundColor = UIColor.redColor()
    }
    複製程式碼
  • unowned 類似oc的unretain ,即使原來引用的物件釋放了,也會對釋放的物件,持有一個無效的引用,不是可選的,不可能指向nil

    httpTool.loadData {[unowned self] () -> () in
        print("載入資料完成,更新介面:", NSThread.currentThread())
        self.view.backgroundColor = UIColor.redColor()
    }
    複製程式碼

17.懶載入

  • 希望所有的物件,只有載入的時候才能加入到記憶體中,

  • lazy 關鍵字,是專門修飾懶載入屬性的

  • 格式

    lazy var 變數名 = { 建立變數程式碼 }()
    複製程式碼
  • 使用

    // 懶載入的本質是,在第一次使用的時候執行閉包,將閉包的返回值賦值給屬性
    // lazy的作用是隻會賦值一次
    lazy var array : [String] = {
        () -> [String] in
        return ["why", "lmj", "lnj"]
    }()
    複製程式碼

18.便利建構函式

  • convenience : 便利,使用convenience修飾的建構函式叫做便利建構函式

  • 便利建構函式通常用在對系統的類進行建構函式的擴充時使用

  • 便利建構函式的特點

  • 便利建構函式,一般寫在extension中

  • 便利建構函式,在init前面新增convenience 關鍵字

  • 在便利構造器中需要明確呼叫self.init(), 而且是先呼叫。

  • 在繼承中,重寫父類的方法中,初始化自己的方法中,先初始化自己的屬性,之後呼叫父類的super.init()

19 #Selector() 事件監聽

  • 事件監聽本質傳送訊息.但是傳送訊息是OC的特性

  • 將方法包裝成@SEL --> 類中查詢方法列表 --> 根據@SEL找到imp指標(函式指標) --> 執行函式

  • 如果swift中將一個函式宣告稱private,那麼該函式不會被新增到方法列表中

  • 如果在private前面加上@objc,那麼該方法依然會被新增到方法列表中

20.型別轉換

  • 型別轉換在 Swift 中使用isas操作符實現 ,你也可以用它來檢查一個型別是否實現了某個協議,就像在檢驗協議的一致性部分講述的一樣。

  • 定一個類MediaItem,name 屬性,init(name:) 方法

  • 其2個子類MovieSong

  • 檢查型別

  • is判斷是一個例項,是否屬於特定子類 if item is Movie

  • 向下轉型

  • 使用子類特有的屬性和方法,使用as 轉化為子類 as?和as!

21.Any 和 AnyObject 的型別轉換

  • Any 表示任何型別,包括函式型別
  • AnyObject表示任何型別的例項
    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("some other double value that I don't want to print")
        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 movie as Movie:
            print("a movie called '\(movie.name)', dir. \(movie.director)")
        case let stringConverter as String -> String:
            print(stringConverter("Michael"))
        default:
            print("something else")
        }
    }
    
    // zero as an Int
    // zero as a Double
    // an integer value of 42
    // a positive double value of 3.14159
    // a string value of "hello"
    // an (x, y) point at 3.0, 5.0
    // a movie called 'Ghostbusters', dir. Ivan Reitman
    // Hello, Michael
    複製程式碼

22.在一個型別中巢狀另外一個型別

  • BlackjackCard(二十一點),結構體中,巢狀Suit,Rank 兩個列舉

    struct BlackjackCard {
    
        // 巢狀的 Suit 列舉
        enum Suit: Character {
            case Spades = "♠",
                Hearts = "♡", 
                Diamonds = "♢", 
                Clubs = "♣"
        }
    
        // 巢狀的 Rank 列舉
        enum Rank: Int {
            case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
            case Jack, Queen, King, Ace
            struct Values {
                let first: Int, second: Int?
            }
    
            var values: Values {
                switch self {
                    case .Ace:
                        return Values(first: 1, second: 11)
                    case .Jack, .Queen, .King:
                        return Values(first: 10, second: nil)
                    default:
                        return Values(first: self.rawValue, second: nil)
                }
            }
        }
    
        // BlackjackCard 的屬性和方法
        let rank: Rank, suit: Suit
        var description: String {
            var output = "suit is \(suit.rawValue),"
            output += " value is \(rank.values.first)"
            if let second = rank.values.second {
                output += " or \(second)"
            }
            return output
        }
    }
    複製程式碼
  • 初始化 let theAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)

  • 使用:let heartsSymbol = BlackjackCard.Suit.Hearts.rawValue

相關文章