Swift 2.2 - 介紹與基礎(chǔ)語(yǔ)法

Swift 介紹

簡(jiǎn)介

  • Swift 語(yǔ)言由蘋(píng)果公司在 2014 年推出,用來(lái)撰寫(xiě) OS X 和 iOS 應(yīng)用程序
  • 2014 年,在 Apple WWDC 發(fā)布
    • 幾家歡喜,幾家愁
    • 愁者:只學(xué)Object-C的人
    • 歡喜者:之前做過(guò)java/python/js語(yǔ)言的人

歷史

  • 2010 年 7 月,蘋(píng)果開(kāi)發(fā)者工具部門(mén)總監(jiān) Chris Lattner 開(kāi)始著手 Swift 編程語(yǔ)言的設(shè)計(jì)工作
  • 用一年時(shí)間,完成基本架構(gòu)
  • Swift 大約歷經(jīng) 4 年的開(kāi)發(fā)期,2014 年 6 月發(fā)表
  • 克里斯·拉特納何許人?LLVM 項(xiàng)目的主要發(fā)起人與作者之一Clang 編譯器的作者蘋(píng)果公司『開(kāi)發(fā)者工具』部門(mén)的主管領(lǐng)導(dǎo)Xcode、Instruments等編譯器團(tuán)隊(duì)Swift的大部分基礎(chǔ)架構(gòu)均由他1人完成評(píng)價(jià):大神中的大神牛逼中的牛逼

特點(diǎn)

  • 特點(diǎn)
    • 從它的語(yǔ)法中能看到Objective-C、JavaScript、C#、Python等語(yǔ)言的影子
    • 語(yǔ)法簡(jiǎn)單、代碼簡(jiǎn)潔、使用方便
    • 可與Objective-C混合使用(相互調(diào)用)
    • 提供了類似 Java 的名字空間(namespace)、泛型(generic)、運(yùn)算對(duì)象重載(operator overloading)
  • 為什么設(shè)計(jì)Swift語(yǔ)言
    • 讓?xiě)?yīng)用開(kāi)發(fā)更簡(jiǎn)單、更快、更穩(wěn)定
    • 確保最終應(yīng)用有著更好的質(zhì)量

重要性

  • 蘋(píng)果目前在大力推廣Swift
  • 斯坦福大學(xué)的公開(kāi)課目前也是使用Swift在授課.因?yàn)橐院骃wift必將代替OC
  • 題外話:我們同學(xué)去面試,面試官問(wèn)是否會(huì)Swift,如果會(huì),我們下個(gè)項(xiàng)目直接用Swift來(lái)寫(xiě).你可以教我們Swift.
  • 個(gè)人建議:
    • 先掌握Swift最基本的語(yǔ)法
    • 高級(jí)/特殊的功能隨著學(xué)習(xí)的深入再深入研究
    • 千萬(wàn)不要浮躁(前面班級(jí)經(jīng)驗(yàn))
      • Swift并不難
      • 但是語(yǔ)法和OC區(qū)別非常非常大
      • 如果是一個(gè)聽(tīng)一聽(tīng),聽(tīng)不懂就算了的心態(tài).一定是學(xué)不好的
      • 如果想要學(xué)習(xí),就認(rèn)真聽(tīng)講,好好練習(xí)

資源網(wǎng)站

Swift初體驗(yàn)

  • Playground是什么?
    • 從Xcode6開(kāi)始出現(xiàn)(Swift開(kāi)始出現(xiàn))
    • 翻譯為:操場(chǎng)/游樂(lè)場(chǎng)
    • 對(duì)于學(xué)習(xí)Swift基本語(yǔ)法非常方便
      • 所見(jiàn)即所得(快速查看結(jié)果)
      • 語(yǔ)法特性發(fā)生改變時(shí),可以快速查看.
  • Swift最基本的語(yǔ)法變化
    • 導(dǎo)入框架 import UIKit
    • 定義標(biāo)識(shí)符時(shí),必須聲明該標(biāo)識(shí)符是變量還是常量
      • 聲明標(biāo)識(shí)符的格式:變量/常量關(guān)鍵字 名稱 : 數(shù)據(jù)類型
    • 語(yǔ)句結(jié)束時(shí)不需要加;
      • 如果同一行有多個(gè)語(yǔ)句,則依然需要加
      • 但是不建議一行多條語(yǔ)句
    • Swift中的打印語(yǔ)句:print(打印的內(nèi)容)

常量&變量

什么是常量和變量

  • 在Swift中規(guī)定:在定義一個(gè)標(biāo)識(shí)符時(shí)必須明確說(shuō)明該標(biāo)識(shí)符是一個(gè)常量還是變量
  • 使用let來(lái)定義常量,定義之后不可以修改
  • 使用var來(lái)定義變量,定義之后可以修改

變量的基本使用

import UIKit

let a : Int = 10
// 錯(cuò)誤寫(xiě)法,當(dāng)一個(gè)字段定義為常量時(shí)是不可以修改的
// a = 20

var b : Int = 20
// 因?yàn)閎定義為變量,因此是可以修改的
b = 30

常量和變量的使用注意:

  • 注意:

    • 在真實(shí)使用過(guò)程中,建議先定義常量,如果需要修改再修改為變量(更加安全)
    • 是指向的對(duì)象不可以再進(jìn)行修改.但是可以通過(guò)指針獲得對(duì)象后,修改對(duì)象內(nèi)部的屬性
      // 注意:聲明為常量不可以修改的意思是指針不可以再指向其他對(duì)象.但是可以通過(guò)指針拿到對(duì)象,修改其中的屬性
      // view : UIView = [[UIView alloc] init];
      // Swift對(duì)象中不需要*
      var view : UIView = UIView()
      view = UIView()
    
      let view1 : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
      view1.backgroundColor = UIColor.redColor()
    
      // 枚舉類型的用法:類型.枚舉的值
      let btn : UIButton = UIButton(type: UIButtonType.Custom)
      btn.backgroundColor = UIColor.blueColor()
      btn.setTitle("按鈕", forState: UIControlState.Normal)
      btn.frame = CGRect(x: 20, y: 20, width: 60, height: 30)
      view1.addSubview(btn)
    

Swift中數(shù)據(jù)類型

Swift類型的介紹

  • Swift中的數(shù)據(jù)類型也有:整型/浮點(diǎn)型/對(duì)象類型/結(jié)構(gòu)體類型等等

  • 先了解整型和浮點(diǎn)型

  • 整型

    • 有符號(hào)
      • Int8 : 有符號(hào)8位整型
      • Int16 : 有符號(hào)16位整型
      • Int32 : 有符號(hào)32位整型
      • Int64 : 有符號(hào)64位整型
      • Int : 和平臺(tái)相關(guān)(默認(rèn),相當(dāng)于OC的NSInteger)
    • 無(wú)符號(hào)
      • UInt8 : 無(wú)符號(hào)8位整型
      • UInt16 : 無(wú)符號(hào)16位整型
      • UInt32 : 無(wú)符號(hào)32位整型
      • UInt64 : 無(wú)符號(hào)64位整型
      • UInt : 和平臺(tái)相關(guān)(常用,相當(dāng)于OC的NSUInteger)(默認(rèn))
  • 浮點(diǎn)型

    • Float : 32位浮點(diǎn)型
    • Double : 64浮點(diǎn)型(默認(rèn))
    // 定義一個(gè)Int類型的變量m,并且賦值為10
    var m : Int = 10
    // 定義一個(gè)Double類型的常量n,并且賦值為3.14
    let n : Double = 3.14
    

Swift中的類型推導(dǎo)

  • Swift是強(qiáng)類型的語(yǔ)言

  • Swift中任何一個(gè)標(biāo)識(shí)符都有明確的類型

  • 注意:

    • 如果定義一個(gè)標(biāo)識(shí)符時(shí)有直接進(jìn)行賦值,那么標(biāo)識(shí)符后面的類型可以省略.
    • 因?yàn)镾wift有類型推導(dǎo),會(huì)自動(dòng)根據(jù)后面的賦值來(lái)決定前面的標(biāo)識(shí)符的數(shù)據(jù)類型
    • 可以通過(guò)option+鼠標(biāo)左鍵來(lái)查看變量的數(shù)據(jù)類型
      // 定義變量時(shí)沒(méi)有指定明確的類型,但是因?yàn)橘x值給i一個(gè)20.20為整型.因此i為整型
      var i = 20
      // 錯(cuò)誤寫(xiě)法:如果之后賦值給i一個(gè)浮點(diǎn)型數(shù)值,則會(huì)報(bào)錯(cuò)
      // i = 30.5
    
      // 正確寫(xiě)法
      var j = 3.33
      j = 6.66
    

Swift中基本運(yùn)算

  • Swift中在進(jìn)行基本運(yùn)算時(shí)必須保證類型一致,否則會(huì)出錯(cuò)

    • 相同類型之間才可以進(jìn)行運(yùn)算
    • 因?yàn)镾wift中沒(méi)有隱式轉(zhuǎn)換
  • 數(shù)據(jù)類型的轉(zhuǎn)化

    • Int類型轉(zhuǎn)成Double類型:Double(標(biāo)識(shí)符)
    • Double類型轉(zhuǎn)成Int類型:Int(標(biāo)識(shí)符)
      let a = 10
      let b = 3.14
    
      // 錯(cuò)誤寫(xiě)法
      // let c = a + b
      // let c = a * b
    
      // 正確寫(xiě)法
      let c = Double(a) + b
      let d = a + Int(b)
    

邏輯分支

一. 分支的介紹

  • 分支即if/switch/三目運(yùn)算符等判斷語(yǔ)句
  • 通過(guò)分支語(yǔ)句可以控制程序的執(zhí)行流程

二. if分支語(yǔ)句

  • 和OC中if語(yǔ)句有一定的區(qū)別

    • 判斷句可以不加()
    • 在Swift的判斷句中必須有明確的真假
      • 不再有非0即真
      • 必須有明確的Bool值
      • Bool有兩個(gè)取值:false/true
        // 演練一:
        let a = 10
    
        // 錯(cuò)誤寫(xiě)法:
        //if a {
        //    print("a")
        //}
    
        // 正確寫(xiě)法
        if a > 9 {
            print(a)
        }
    
        // 演練二:
        let score = 87
    
        if score < 60 {
            print("不及格")
        } else if score <= 70 {
            print("及格")
        } else if score <= 80 {
            print("良好")
        } else if score <= 90 {
            print("優(yōu)秀")
        } else {
            print("完美")
        }
    
        // 演練三:
        // 這個(gè)是可選類型,因?yàn)橹挥新暶鞒煽蛇x類型后,才可以判斷是否為空
        // 可選類型會(huì)在后續(xù)講解,可先了解即可
        let view : UIView? = UIView()
    
        // 判斷如果view有值,則設(shè)置背景
        // 錯(cuò)誤寫(xiě)法
        //if view {
        //    view.backgroundColor = UIColor.redColor()
        //}
    
        if view != nil {
            view!.backgroundColor = UIColor.redColor()
        }
    

三. 三目運(yùn)算符

  • Swift 中的 三目 運(yùn)算保持了和 OC 一致的風(fēng)格

    var a = 10
    var b = 50
    
    var result = a > b ? a : b
    println(result)
    

四.guard的使用

  • guard是Swift2.0新增的語(yǔ)法

  • 它與if語(yǔ)句非常類似,它設(shè)計(jì)的目的是提高程序的可讀性

  • guard語(yǔ)句必須帶有else語(yǔ)句,它的語(yǔ)法如下:

    • 當(dāng)條件表達(dá)式為true時(shí)候跳過(guò)else語(yǔ)句中的內(nèi)容,執(zhí)行語(yǔ)句組內(nèi)容
      guard 條件表達(dá)式 else {
          // 條換語(yǔ)句
          break
      }
      語(yǔ)句組
    
  • 例子

      var age = 18
    
      func online(age : Int) -> Void {
          guard age >= 18 else {
              print("回家去")
              return
          }
      
          print("可以上網(wǎng)")
      }
      
      online(age)
    

四.switch分支

switch的介紹
  • Switch作為選擇結(jié)構(gòu)中必不可少的語(yǔ)句也被加入到了Swift中
  • 只要有過(guò)編程經(jīng)驗(yàn)的人對(duì)Switch語(yǔ)句都不會(huì)感到陌生
  • 但蘋(píng)果對(duì)Switch進(jìn)行了大大的增強(qiáng),使其擁有其他語(yǔ)言中沒(méi)有的特性
switch的簡(jiǎn)單使用
  • 基本用法和OC用法一致

  • 不同之處:

    • switch后可以不跟()
    • case后可以不跟break(默認(rèn)會(huì)有break)
  • 例子:

      let sex = 0
    
      switch sex {
      case 0 :
          print("男")
      case 1 :
          print("女")
      default :
          print("其他")
      }
    
  • 簡(jiǎn)單使用補(bǔ)充:

    • 一個(gè)case判斷中,可以判斷多個(gè)值
    • 多個(gè)值以,隔開(kāi)
      let sex = 0
    
      switch sex {
      case 0, 1:
          print("正常人")
      default:
          print("其他")
      }
    
  • 簡(jiǎn)單使用補(bǔ)充:

    • 如果希望出現(xiàn)之前的case穿透,則可以使用關(guān)鍵字fallthrough
      let sex = 0
    
      switch sex {
      case 0:
          fallthrough
      case 1:
          print("正常人")
      default:
          print("其他")
      }
    
Switch支持多種數(shù)據(jù)類型
  • 浮點(diǎn)型的switch判斷

      let f = 3.14
      switch f {
      case 3.14:
          print("π")
      default:
          print("not π")
      }
    
  • 支持字符串類型

    • 字符串的使用后面會(huì)詳細(xì)講解
      let m = 5
      let n = 10
      var result = 0
    
      let opration = "+"
    
      switch opration {
          case "+":
              result = m + n
          case "-":
              result = m - n
          case "*":
              result = m * n
          case "/":
              result = m / n
      default:
          result = 0
      }
    
      print(result)
    
switch支持區(qū)間判斷
  • 什么是區(qū)間?

    • 通常我們指的是數(shù)字區(qū)間:010,100200
  • swift中的區(qū)間常見(jiàn)有兩種

    • 半開(kāi)半閉區(qū)間:0..<10 表示:0~9,不包括10
    • 閉區(qū)間:0...10 表示:0~10
      let score = 88
    
      switch score {
      case 0..<60:
          print("不及格")
      case 60..<80:
          print("幾個(gè)")
      case 80..<90:
          print("良好")
      case 90..<100:
          print("優(yōu)秀")
      default:
          print("滿分")
      }
    

循環(huán)的介紹

  • 在開(kāi)發(fā)中經(jīng)常會(huì)需要循環(huán)
  • 常見(jiàn)的循環(huán)有:for/while/do while.
  • 這里我們只介紹for/while,因?yàn)閒or/while最常見(jiàn)

for循環(huán)的寫(xiě)法

  • 最常規(guī)寫(xiě)法

      // 傳統(tǒng)寫(xiě)法
      for var i = 0; i < 10; i++ {
          print(i)
      }
    
  • 區(qū)間for循環(huán)

      for i in 0..<10 {
          print(i)
      }
      
      for i in 0...10 {
          print(i)
      }
    
  • 特殊寫(xiě)法

    - 如果在for循環(huán)中不需要用到下標(biāo)i
      for _ in 0..<10 {
          print("hello")
      }
    

while和do while循環(huán)

  • while循環(huán)

    • while的判斷句必須有正確的真假,沒(méi)有非0即真
    • while后面的()可以省略
      var a = 0
      while a < 10 {
          a++
      }
    
  • do while循環(huán)

    • 使用repeat關(guān)鍵字來(lái)代替了do
      let b = 0
      repeat {
          print(b)
          b++
      } while b < 20
    

字符串的介紹

  • 字符串在任何的開(kāi)發(fā)中使用都是非常頻繁的
  • OC和Swift中字符串的區(qū)別
    • 在OC中字符串類型時(shí)NSString,在Swift中字符串類型是String
    • OC中字符串@"",Swift中字符串""
  • 使用 String 的原因String 是一個(gè)結(jié)構(gòu)體,性能更高NSString 是一個(gè) OC 對(duì)象,性能略差String 支持直接遍歷Swift 提供了 StringNSString 之間的無(wú)縫轉(zhuǎn)換

字符的定義

  • 定義不可變字符串

      let str = "hello Objective-C"
    
  • 定義可變字符串

      var str = "hello Swift"
    

字符串的使用

獲取字符串的長(zhǎng)度
  • 獲取字符集合,再獲取集合的count屬性

      let count = str.characters.count
    
遍歷字符串
    // 字符串遍歷
    var str = "Hello, Swift"
    for c in str.characters {
        print(c)
    }
字符串拼接
  • 兩個(gè)字符串的拼接

      let str1 = "Hello"
      let str2 = "World"
      let str3 = str1 + str2
    
  • 字符串和其他數(shù)據(jù)類型的拼接

      let name = "why"
      let age = 18
      
      let info = "my name is \(name), age is \(age)"
    
  • 字符串的格式化

    • 比如時(shí)間:03:04
      let min = 3
      let second = 4
    
      let time = String(format: "%02d:%02d", arguments: [min, second])
    
字符串的截取
  • Swift中提供了特殊的截取方式

    • 該方式非常麻煩
    • Index創(chuàng)建較為麻煩
  • 簡(jiǎn)單的方式是將String轉(zhuǎn)成NSString來(lái)使用

    • 在標(biāo)識(shí)符后加:as NSString即可
      let myStr = "www.baidu.com"
      var subStr = (myStr as NSString).substringFromIndex(4)
      subStr = (myStr as NSString).substringToIndex(3)
      subStr = (myStr as NSString).substringWithRange(NSRange(location: 4, length: 5))
    
  • swift截取方式

      // 1.定義字符串
      let str = "www.baidu.com"
      
      // 2.截取開(kāi)始位置
      let fromIndex = str.startIndex.advancedBy(3)
      let header = str.substringFromIndex(fromIndex)
      
      // 3.截取結(jié)束位置
      let toIndex = str.endIndex.advancedBy(-3)
      let footer = str.substringToIndex(toIndex)
      
      // 4.截取中間的字符串
      let range = Range(start: str.startIndex.advancedBy(4), end: str.endIndex.advancedBy(-4))
      let middle = str.substringWithRange(range)
    

數(shù)組

數(shù)組的介紹

  • 數(shù)組(Array)是一串有序的由相同類型元素構(gòu)成的集合
  • 數(shù)組中的集合元素是有序的,可以重復(fù)出現(xiàn)
  • Swift中的數(shù)組
    • swift數(shù)組類型是Array,是一個(gè)泛型集合

數(shù)組的初始化

  • 數(shù)組分成:可變數(shù)組和不可變數(shù)組

    • 使用let修飾的數(shù)組是不可變數(shù)組
    • 使用var修飾的數(shù)組是可變數(shù)組
      // 定義一個(gè)可變數(shù)組,必須初始化才能使用
      var array1 : [String] = [String]()
    
      // 定義一個(gè)不可變數(shù)組
      let array2 : [NSObject] = ["why", 18]
    
  • 在聲明一個(gè)Array類型的時(shí)候可以使用下列的語(yǔ)句之一

      var stuArray1:Array<String>
      var stuArray2: [String]
    
  • 聲明的數(shù)組需要進(jìn)行初始化才能使用,數(shù)組類型往往是在聲明的同時(shí)進(jìn)行初始化的

      // 定義時(shí)直接初始化
      var array = ["why", "lnj", "lmj"]
      // 先定義,后初始化
      var array : Array<String>
      array = ["why", "lnj", "lmj"]
    

對(duì)數(shù)組的基本操作

    // 添加數(shù)據(jù)
    array.append("yz")
    
    // 刪除元素
    array.removeFirst()
    
    // 修改元素
    array[0] = "why"
    
    // 取值
    array[1]

數(shù)組的遍歷

    // 遍歷數(shù)組
    for i in 0..<array.count {
        print(array[i])
    }
    
    // forin方式
    for item in array {
        print(item)
    }
    
    // 設(shè)置遍歷的區(qū)間
    for item in array[0..<2] {
        print(item)
    }
    
    // 遍歷數(shù)組的同時(shí)獲取下標(biāo)值
    let names = ["why", "yz", "lnj", "lmj"]
    for (index, name) in names.enumerate() {
        print(index)
        print(name)
    }

數(shù)組的合并

    // 數(shù)組合并
    // 注意:只有相同類型的數(shù)組才能合并
    var array = ["why", "lmj","lnj"]
    var array1 = ["yz", "wsz"]
    var array2 = array + array1;
    
    // 不建議一個(gè)數(shù)組中存放多種類型的數(shù)據(jù)
    var array3 = [2, 3, "why"]
    var array4 = ["yz", 23]
    array3 + array4

字典

字典的介紹

  • 字典允許按照某個(gè)鍵來(lái)訪問(wèn)元素
  • 字典是由兩部分集合構(gòu)成的,一個(gè)是鍵(key)集合,一個(gè)是值(value)集合
  • 鍵集合是不能有重復(fù)元素的,而值集合是可以重復(fù)的,鍵和值是成對(duì)出現(xiàn)的
  • Swift中的字典
    • Swift字典類型是Dictionary,也是一個(gè)泛型集合

字典的初始化

  • Swift中的可變和不可變字典

    • 使用let修飾的數(shù)組是不可變字典
    • 使用var修飾的數(shù)組是可變字典
      // 定義一個(gè)可變字典
      var dict1 : [String : NSObject] = [String : NSObject]()
    
      // 定義一個(gè)不可變字典
      let dict2 = ["name" : "why", "age" : 18]
    
  • 在聲明一個(gè)Dictionary類型的時(shí)候可以使用下面的語(yǔ)句之一

      var dict1: Dictionary<Int, String>
      var dict2: [Int: String]
    
  • 聲明的字典需要進(jìn)行初始化才能使用,字典類型往往是在聲明的同時(shí)進(jìn)行初始化的

      // 定時(shí)字典的同時(shí),進(jìn)行初始化
      var dict = ["name" : "why", "age" : 18]
    

// swift中任意對(duì)象,通常不使用NSObject,使用AnyObject
var dict : Dictionary<String, AnyObject>
dict = ["name" : "why", "age" : 18]
?```

字典的基本操作

    // 添加數(shù)據(jù)
    dict["height"] = 1.88
    dict["weight"] = 70.0
    dict
    
    // 刪除字段
    dict.removeValueForKey("height")
    dict
    
    // 修改字典
    dict["name"] = "lmj"
    dict.updateValue("lmj", forKey: "name")
    dict
    
    // 查詢字典
    dict["name"]

字典的遍歷

    // 遍歷字典中所有的值
    for value in dict.values {
        print(value)
    }
    // 遍歷字典中所有的鍵
    for key in dict.keys {
        print(key)
    }
    
    // 遍歷所有的鍵值對(duì)
    for (key, value) in dict {
        print(key)
        print(value)
    }

字典的合并

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

元組

元組的介紹

  • 元組是Swift中特有的,OC中并沒(méi)有相關(guān)類型
  • 它是什么呢?
    • 它是一種數(shù)據(jù)結(jié)構(gòu),在數(shù)學(xué)中應(yīng)用廣泛
    • 類似于數(shù)組或者字典
    • 可以用于定義一組數(shù)據(jù)
    • 組成元組類型的數(shù)據(jù)可以稱為“元素”

元組的定義

  • 元組的常見(jiàn)寫(xiě)法

      // 使用元組描述一個(gè)人的信息
      ("1001", "張三", 30, 90)
      // 給元素加上元素名稱,之后可以通過(guò)元素名稱訪問(wèn)元素
      (id:"1001", name:"張三", english_score:30, chinese_score:90)
    

元組的簡(jiǎn)單使用

  • 用元組來(lái)描述一個(gè)HTTP的錯(cuò)誤信息

      // 元組:HTTP錯(cuò)誤
      // let array = [404, "Not Found"]
      // 寫(xiě)法一:
      let error = (404, "Not Found")
      print(error.0)
      print(error.1)
      
      // 寫(xiě)法二:
      let error = (errorCode : 404, errorInfo : "Not Found")
      print(error.errorCode)
      print(error.errorInfo)
      
      // 寫(xiě)法三:
      let (errorCode, errorIno) = (404, "Not Found")
      print(errorCode)
      print(errorIno)
    

可選類型

可選類型的介紹

  • 注意:
    • 可選類型時(shí)swift中較理解的一個(gè)知識(shí)點(diǎn)
    • 暫時(shí)先了解,多利用Xcode的提示來(lái)使用
    • 隨著學(xué)習(xí)的深入,慢慢理解其中的原理和好處
  • 概念:
    • 在OC開(kāi)發(fā)中,如果一個(gè)變量暫停不使用,可以賦值為0(基本屬性類型)或者賦值為空(對(duì)象類型)
    • 在swift開(kāi)發(fā)中,nil也是一個(gè)特殊的類型.因?yàn)楹驼鎸?shí)的類型不匹配是不能賦值的(swift是強(qiáng)類型語(yǔ)言)
    • 但是開(kāi)發(fā)中賦值nil,在所難免.因此推出了可選類型
  • 可選類型的取值:
    • 空值
    • 有值

定義可選類型

  • 定義一個(gè)可選類型有兩種寫(xiě)法

    • 最基本的寫(xiě)法
    • 語(yǔ)法糖(常用)
      // 錯(cuò)誤寫(xiě)法
      // let string : String = nil
      // 正確寫(xiě)法:
      // 注意:name的類型是一個(gè)可選類型,但是該可選類型中可以存放字符串.
      // 寫(xiě)法一:定義可選類型
      let name : Optional<String> = nil
    
      // 寫(xiě)法二:定義可選類型,語(yǔ)法糖(常用)
      let name : String? = nil
    

可選類型的使用

    // 演練一:給可選類型賦值
    // 定義可選類型
    var string : Optional<String> = nil
    
    // 給可選類型賦值
    // 錯(cuò)誤寫(xiě)法:因此該可選類型中只能存放字符串
    string = 123
    // 正確寫(xiě)法:
    string = "Hello world"
    
    // 打印結(jié)果
    print(string)
    // 結(jié)果:Optional("Hello world")\n
    // 因?yàn)榇蛴〕鰜?lái)的是可選類型,所有會(huì)帶Optional


    // 演練二:取出可選類型的值
    // 取出可選類型的真實(shí)值(解包)
    print(string!)
    // 結(jié)果:Hello world\n
    
    // 注意:如果可選類型為nil,強(qiáng)制取出其中的值(解包),會(huì)出錯(cuò)
    string = nil
    print(string!) // 報(bào)錯(cuò)
    
    // 正確寫(xiě)法:
    if string != nil {
        print(string!)
    }
    
    // 簡(jiǎn)單寫(xiě)法:為了讓在if語(yǔ)句中可以方便使用string
    // 可選綁定
    if let str = string {
        print(str)
    }

真實(shí)應(yīng)用場(chǎng)景

  • 目的:讓代碼更加嚴(yán)謹(jǐn)

      // 通過(guò)該方法創(chuàng)建的URL,可能有值,也可能沒(méi)有值.
      // 錯(cuò)誤寫(xiě)法:如果返回值是nil時(shí),就不能接收了
      // 如果字符串中有中文,則返回值為nil,因此該方法的返回值就是一個(gè)可選類型,而使用一個(gè)NSURL類型接收是錯(cuò)誤的
      let url : NSURL = NSURL(string: "www.baidu.com")
      
      // 正確寫(xiě)法:使用可選類型來(lái)接收
      let url : NSURL? = NSURL(string: "www.baidu.com")
      // 該方式利用類型推導(dǎo)
      let url = NSURL(string: "www.baidu.com")
      
      // 通過(guò)url來(lái)創(chuàng)建request對(duì)象:在使用可選類型前要先進(jìn)行判斷是否有值
      // 該語(yǔ)法成為可選綁定(如果url有值就解包賦值給tempURL,并且執(zhí)行{})
      if let tempUrl = url {
          let request = NSURLRequest(URL: tempUrl)
      }
    

類型轉(zhuǎn)化

常見(jiàn)的類型轉(zhuǎn)化符號(hào)

  • is : 用于判斷一個(gè)實(shí)例是否是某一種類型
  • as : 將實(shí)例轉(zhuǎn)成某一種類型

例子

    // 1.定義數(shù)組
    let array : [AnyObject] = [12, "why", 1.88]
    
    // 2.取出數(shù)組中的第一個(gè)元素
    let objc = array.first!
    
    // 3.判斷第一個(gè)元素是否是一個(gè)Int類型
    if objc is Int {
        print("是Int類型")
    } else {
        print("非Int類型")
    }
    
    // 4.將objc轉(zhuǎn)成真正的類型來(lái)使用
    // 4.1.as? 將AnyObject轉(zhuǎn)成可選類型,通過(guò)判斷可選類型是否有值,來(lái)決定是否轉(zhuǎn)化成功了
    let age = objc as? Int
    print(age) // 結(jié)果:Optional(12)
    
    // 4.2.as! 將AnyObject轉(zhuǎn)成具體的類型,但是注意:如果不是該類型,那么程序會(huì)崩潰
    let age1 = objc as! Int
    print(age1) // 結(jié)果:12

函數(shù)

函數(shù)的介紹

  • 函數(shù)相當(dāng)于OC中的方法

  • 函數(shù)的格式如下

      func 函數(shù)名(參數(shù)列表) -> 返回值類型 {
          代碼塊
          return 返回值
      }
    
  • func是關(guān)鍵字,多個(gè)參數(shù)列表之間可以用逗號(hào)(,)分隔,也可以沒(méi)有參數(shù)

  • 使用箭頭“->”指向返回值類型

  • 如果函數(shù)沒(méi)有返回值,返回值為Void.并且“-> 返回值類型”部分可以省略

常見(jiàn)的函數(shù)類型

    // 1.沒(méi)有參數(shù),沒(méi)用返回值
    func about() -> Void {
        print("iphone6s plus")
    }
    // 調(diào)用函數(shù)
    about()
    
    // 簡(jiǎn)單寫(xiě)法
    // 如果沒(méi)用返回值,Void可以寫(xiě)成()
    func about1() -> () {
        print("iphone6s plus")
    }
    // 如果沒(méi)有返回值,后面的內(nèi)容可以都不寫(xiě)
    func about2() {
        print("iphone6s plus")
    }
    
    about2()
    
    // 2.有參數(shù),沒(méi)用返回值
    func callPhone(phoneNum : String) {
        print("打電話給\(phoneNum)")
    }
    callPhone("+86 110")
    
    // 3.沒(méi)用參數(shù),有返回值
    func readMessage() -> String {
        return "吃飯了嗎?"
    }
    var str = readMessage()
    print(str)
    
    // 4.有參數(shù),有返回值
    func sum(num1 : Int, num2 : Int) -> Int {
        return num1 + num2
    }
    var result = sum(20, num2: 30)
    print(result)
    
    // 5.有多個(gè)返回值的函數(shù)
    let nums = [1, 3, 4, 8, 22, 23]
    func getNumCount(nums : [Int]) -> (oddCount : Int, evenCount : Int) {
        var oddCount = 0
        var evenCount = 0
        for num in nums {
            if num % 2 == 0 {
                oddCount++
            } else {
                evenCount++
            }
        }
        return (oddCount, evenCount)
    }
    
    let result = getNumCount(nums)
    result.oddCount
    result.evenCount

函數(shù)的使用注意

  • 注意一: 外部參數(shù)和內(nèi)部參數(shù)

    • 在函數(shù)內(nèi)部可以看到的參數(shù),就是內(nèi)部參數(shù)
    • 在函數(shù)外面可以看到的參數(shù),就是外部參數(shù)
    • 默認(rèn)情況下,從第二個(gè)參數(shù)開(kāi)始,參數(shù)名稱既是內(nèi)部參數(shù)也是外部參數(shù)
    • 如果第一個(gè)參數(shù)也想要有外部參數(shù),可以設(shè)置標(biāo)簽:在變量名前加標(biāo)簽即可
    • 如果不想要外部參數(shù),可以在參數(shù)名稱前加_
      // num1和a是外部參數(shù)的名稱
      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)
    
      // 方法的重載:方法名稱相同,但是參數(shù)不同,可以稱之為方法的重載(了解)
      func ride(num1: Int, _ num2 :Int) -> Int {
          return num1 * num2
      }
    
      var result2 = ride(20, 20)
    
  • 注意二: 默認(rèn)參數(shù)

    • 某些情況,如果沒(méi)有傳入具體的參數(shù),可以使用默認(rèn)參數(shù)
      func makecoffee(type :String = "卡布奇諾") -> String {
          return "制作一杯\(type)咖啡。"
      }
    
      let coffee1 = makecoffee("拿鐵")
      let coffee2 = makecoffee()
    
  • 注意三: 可變參數(shù)

    • swift中函數(shù)的參數(shù)個(gè)數(shù)可以變化,它可以接受不確定數(shù)量的輸入類型參數(shù)
    • 它們必須具有相同的類型
    • 我們可以通過(guò)在參數(shù)類型名后面加入(...)的方式來(lái)指示這是可變參數(shù)
      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)
    
  • 注意四: 引用類型(指針的傳遞)

    • 默認(rèn)情況下,函數(shù)的參數(shù)是值傳遞.如果想改變外面的變量,則需要傳遞變量的地址
    • 必須是變量,因?yàn)樾枰趦?nèi)部改變其值
    • Swift提供的inout關(guān)鍵字就可以實(shí)現(xiàn)
    • 對(duì)比下列兩個(gè)函數(shù)
      // 函數(shù)一:值傳遞
      func swap(var a : Int, var b : Int) {
          let temp = a;
          a = b;
          b = temp
          
          print("a:\(a), b:\(b)")
      }
    
      var a = 10
      var b = 20
      swap(a, b: b)
      print("a:\(a), b:\(b)")
    
      // 函數(shù)二:指針的傳遞
      func swap1(inout a : Int, inout b : Int) {
          let temp = a
          a = b
          b = temp
          
          print("a:\(a), b:\(b)")
      }
    
      swap1(&a, b: &b)
      print("a:\(a), b:\(b)")
    
  • 函數(shù)的嵌套使用

    • swift中函數(shù)可以嵌套使用
    • 即函數(shù)中包含函數(shù),但是不推薦該寫(xiě)法
      // 函數(shù)的嵌套
      let value = 55
      func test() {
          func demo() {
              print("demo \(value)")
          }
          
          print("test")
          demo()
      }
    
      demo() // 錯(cuò)誤
      test() // 執(zhí)行函數(shù)會(huì)先打印'test',再打印'demo'
    

函數(shù)的類型

  • 函數(shù)類型的概念

    • 每個(gè)函數(shù)都有屬于自己的類型,由函數(shù)的參數(shù)類型和返回類型組成
      • 這個(gè)例子中定義了兩個(gè)簡(jiǎn)單的數(shù)學(xué)函數(shù):addTwoInts 和 multiplyTwoInts
      • 這兩個(gè)函數(shù)都傳入兩個(gè) Int 類型, 返回一個(gè)合適的Int值
      • 這兩個(gè)函數(shù)的類型是 (Int, Int) -> Int
        // 定義兩個(gè)函數(shù)
        func addTwoInts(a : Int, b : Int) -> Int {
            return a + b
        }
    
        func multiplyTwoInt(a : Int, b : Int) -> Int {
            return a * b
        }
    
  • 抽取兩個(gè)函數(shù)的類型,并且使用

      // 定義函數(shù)的類型
      var mathFunction : (Int, Int) -> Int = addTwoInts
      
      // 使用函數(shù)的名稱
      mathFunction(10, 20)
      
      // 給函數(shù)的標(biāo)識(shí)符賦值其他值
      mathFunction = multiplyTwoInt
      
      // 使用函數(shù)的名稱
      mathFunction(10, 20)
    
  • 函數(shù)作為方法的參數(shù)

      // 3.將函數(shù)的類型作為方法的參數(shù)
      func printResult(a : Int, b : Int, calculateMethod : (Int, Int) -> Int) {
          print(calculateMethod(a, b))
      }
      
      printResult(10, b: 20, calculateMethod: addTwoInts)
      printResult(10, b: 20, calculateMethod: multiplyTwoInt)
    
  • 函數(shù)作為方法的返回值

      // 1.定義兩個(gè)函數(shù)
      func stepForward(num : Int) -> Int {
          return num + 1
      }
      
      func stepBackward(num : Int) -> Int {
          return num - 1
      }
      
      // 2.定義一個(gè)變量,希望該變量經(jīng)過(guò)計(jì)算得到0
      var num = -4
      
      // 3.定義獲取哪一個(gè)函數(shù)
      func getOprationMethod(num : Int) -> (Int) -> Int {
          return num <= 0 ? stepForward : stepBackward
      }
      
      // 4.for玄幻進(jìn)行操作
      while num != 0 {
          let oprationMethod = getOprationMethod(num)
          num = oprationMethod(num)
          print(num)
      }
    

枚舉類型

枚舉類型的介紹

  • 概念介紹

    • 枚舉定義了一個(gè)通用類型的一組相關(guān)的值,使你可以在你的代碼中以一個(gè)安全的方式來(lái)使用這些值。
    • 在 C/OC 語(yǔ)言中枚舉指定相關(guān)名稱為一組整型值
    • Swift 中的枚舉更加靈活,不必給每一個(gè)枚舉成員提供一個(gè)值.也可以提供一個(gè)值是字符串,一個(gè)字符,或是一個(gè)整型值或浮點(diǎn)值
  • 枚舉類型的語(yǔ)法

    • 使用enum關(guān)鍵詞并且把它們的整個(gè)定義放在一對(duì)大括號(hào)內(nèi)
          enum SomeEnumeration {
          // enumeration definition goes here
          }
    

枚舉類型的定義

  • 以下是指南針?biāo)膫€(gè)方向的一個(gè)例子

    • case關(guān)鍵詞表明新的一行成員值將被定義
    • 不像 C 和 Objective-C 一樣,Swift 的枚舉成員在被創(chuàng)建時(shí)不會(huì)被賦予一個(gè)默認(rèn)的整數(shù)值
    • 在上面的CompassPoints例子中,North,South,East和West不是隱式的等于0,1,2和3
      enum CompassPoint {
        case North
        case South
        case East
        case West
      }
    
  • 定義方式二:多個(gè)成員值可以出現(xiàn)在同一行上

      enum Planet {
        case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
      }
    

給枚舉類型賦值

  • 枚舉類型賦值可以是字符串/字符/整型/浮點(diǎn)型

    • 注意如果有給枚舉類型賦值,則必須在枚舉類型后面明確說(shuō)明具體的類型
      // 1.枚舉類型的賦值
      enum CompassPoint : Int {
        case North = 1
        case South = 2
        case East = 3
        case West = 4
      }
    
      enum Planet {
        case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
      }
      
      // 2.枚舉類型的使用
      let p = Planet(rawValue: 3)
      
      if let p = p {
          switch p {
          case .Mercury:
              print("Mercury")
          case .Venus:
              print("Venus")
          case .Earth:
              print("Mercury")
          case .Mars:
              print("Mars")
          case .Jupiter:
              print("Jupiter")
          case .Saturn:
              print("Saturn")
          case .Uranus:
              print("Uranus")
          case .Neptune:
              print("Neptune")
          }
      }
    

結(jié)構(gòu)體

結(jié)構(gòu)體的介紹

  • 概念介紹

    • 結(jié)構(gòu)體(struct)是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合
    • 結(jié)構(gòu)體(struct)指的是一種數(shù)據(jù)結(jié)構(gòu)
    • 結(jié)構(gòu)體是值類型,在方法中傳遞時(shí)是值傳遞
  • 結(jié)構(gòu)的定義格式

      struct 結(jié)構(gòu)體名稱 {
          // 屬性和方法
      }
    

為什么需要結(jié)構(gòu)體?

  • 先來(lái)看一個(gè)例子
    • 我們要計(jì)算平面坐標(biāo)里某個(gè)點(diǎn)距點(diǎn)Center的距離是否小于200
    • 算起來(lái)很簡(jiǎn)單,勾股定理就搞定了:
      • 其中sqrt(n)用來(lái)計(jì)算n的平方根
      • pow(x, n)用來(lái)計(jì)算x的n次方
      let centerX : Double = 100
      let centerY : Double = 100

      func inRange(x : Double, y : Double) -> Bool {
          let disX = x - centerX
          let disY = y - centerX
          
          let dis = sqrt(pow(disX, 2) + pow(disY, 2))
          
          return dis < 200
      }

      let x : Double = 100
      let y : Double = 1000

      inRange(x, y: y)
  • 問(wèn)題

    • 但是這樣有一個(gè)不足,當(dāng)我們需要比較很多個(gè)點(diǎn)和Center的距離的時(shí)候,這些數(shù)字并不能明確告訴我們它們代表的位置的意義,甚至我們都無(wú)法知道它們代表一個(gè)數(shù)字。
    • 如果我們可以像這樣來(lái)比較位置:
      • 相比數(shù)字,它們看上去就會(huì)直觀的多
      • 而這,就是我們需要自定義struct類型最直接的原因
        inRange(location1)
        inRange(myHome)
    
  • 使用結(jié)構(gòu)進(jìn)行改進(jìn)

      // 初始化結(jié)構(gòu)體
      struct Location {
          var x : Double
          var y : Double
      }
      
      // 創(chuàng)建結(jié)構(gòu)體
      let location = Location(x: 90, y: 90)
      
      // 優(yōu)化剛才的方法
      func inRange(location : Location) -> Bool {
          let disX = location.x - centerX
          let disY = location.y - centerY
      
          let dis = sqrt(pow(disX, 2) + pow(disY, 2))
      
          return dis < 200
      }
      
      inRange(location)
    

結(jié)構(gòu)體的增強(qiáng)

  • 擴(kuò)充構(gòu)造函數(shù)

    • 默認(rèn)情況下創(chuàng)建Location時(shí)使用Location(x: x值, y: y值)
    • 但是為了讓我們?cè)谑褂媒Y(jié)構(gòu)體時(shí)更加的靈活,swift還可以對(duì)構(gòu)造函數(shù)進(jìn)行擴(kuò)充
    • 擴(kuò)充的注意點(diǎn)
      • 在擴(kuò)充的構(gòu)造函數(shù)中必須保證成員變量是有值的
      • 擴(kuò)充的構(gòu)造函數(shù)會(huì)覆蓋原有的構(gòu)造函數(shù)
        struct Location {
            var x : Double
            var y : Double
            
            init(x : Double, y : Double) {
                self.x = x
                self.y = y
            }
            
            init(xyString : String) {
                let strs = xyString.componentsSeparatedByString(",")
                x = Double(strs.first!)!
                y = Double(strs.last!)!
            }
        }
    
        let location = Location(x: 100, y: 100)
        let location1 = Location(xyString: "100,100")
    
  • 為結(jié)構(gòu)體擴(kuò)充方法

    • 為了讓結(jié)構(gòu)體使用更加靈活,swift的結(jié)構(gòu)體中可以擴(kuò)充方法
    • 例子:為了Location結(jié)構(gòu)體擴(kuò)充兩個(gè)方法
      • 向水平方向移動(dòng)的方法
      • 向垂直方向移動(dòng)的方法
        struct Location {
            var x : Double
            var y : Double
            
            init(x : Double, y : Double) {
                self.x = x
                self.y = y
            }
            
            init(xyString : String) {
                let strs = xyString.componentsSeparatedByString(",")
                x = Double(strs.first!)!
                y = Double(strs.last!)!
            }
            
            mutating func moveH(x : Double) {
                self.x += x
            }
            
            mutating func moveV(y : Double) {
                self.y += y
            }
        }
    
  • 注意:

    • 如果我們使用的Location不是自己定義的,但是我們?nèi)耘f希望在自己的項(xiàng)目里擴(kuò)展Location的操作
    • Swift也能幫我們達(dá)成,這個(gè)機(jī)制,叫做extension
      extension Location {
          mutating func moveH(x : Double) {
              self.x += x
          }
          
          mutating func moveV(y : Double) {
              self.y += y
          }
      }
    

Swift中類的使用

主要內(nèi)容

  • 類的介紹和定義
  • 類的屬性
  • 類的構(gòu)造函數(shù)

一. 類的介紹和定義

  • Swift也是一門(mén)面向?qū)ο箝_(kāi)發(fā)的語(yǔ)言

  • 面向?qū)ο蟮幕A(chǔ)是類,類產(chǎn)生了對(duì)象

  • 在Swift中如何定義類呢?

    • class是Swift中的關(guān)鍵字,用于定義類
      class 類名 : SuperClass {
          // 定義屬性和方法
      }
    
  • 注意:

    • 定義的類,可以沒(méi)有父類.那么該類是rootClass
    • 通常情況下,定義類時(shí).繼承自NSObject(非OC的NSObject)

二. 如何定義類的屬性

類的屬性介紹
  • Swift中類的屬性有多種
    • 存儲(chǔ)屬性:存儲(chǔ)實(shí)例的常量和變量
    • 計(jì)算屬性:通過(guò)某種方式計(jì)算出來(lái)的屬性
    • 類屬性:與整個(gè)類自身相關(guān)的屬性
存儲(chǔ)屬性
  • 存儲(chǔ)屬性是最簡(jiǎn)單的屬性,它作為類實(shí)例的一部分,用于存儲(chǔ)常量和變量

  • 可以給存儲(chǔ)屬性提供一個(gè)默認(rèn)值,也可以在初始化方法中對(duì)其進(jìn)行初始化

  • 下面是存儲(chǔ)屬性的寫(xiě)法

    • age和name都是存儲(chǔ)屬性,用來(lái)記錄該學(xué)生的年齡和姓名
    • chineseScore和mathScore也是存儲(chǔ)屬性,用來(lái)記錄該學(xué)生的語(yǔ)文分?jǐn)?shù)和數(shù)學(xué)分?jǐn)?shù)
      class Student : NSObject {
          // 定義屬性
          // 存儲(chǔ)屬性
          var age : Int = 0
          var name : String?
          
          var chineseScore : Double = 0.0
          var mathScore : Double = 0.0
      }
    
      // 創(chuàng)建學(xué)生對(duì)象
      let stu = Student()
    
      // 給存儲(chǔ)屬性賦值
      stu.age = 10
      stu.name = "why"
    
      stu.chineseScore = 89.0
      stu.mathScore = 98.0
    
計(jì)算屬性
  • 計(jì)算屬性并不存儲(chǔ)實(shí)際的值,而是提供一個(gè)getter和一個(gè)可選的setter來(lái)間接獲取和設(shè)置其它屬性

  • 計(jì)算屬性一般只提供getter方法

  • 如果只提供getter,而不提供setter,則該計(jì)算屬性為只讀屬性,并且可以省略get{}

  • 下面是計(jì)算屬性的寫(xiě)法

    • averageScore是計(jì)算屬性,通過(guò)chineseScore和mathScore計(jì)算而來(lái)的屬性
    • 在setter方法中有一個(gè)newValue變量,是系統(tǒng)指定分配的
      class Student : NSObject {
          // 定義屬性
          // 存儲(chǔ)屬性
          var age : Int = 0
          var name : String?
          
          var chineseScore : Double = 0.0
          var mathScore : Double = 0.0
          
          // 計(jì)算屬性
          var averageScore : Double {
              get {
                  return (chineseScore + mathScore) / 2
              }
          
              // 沒(méi)有意義,因?yàn)橹螳@取值時(shí)依然是計(jì)算得到的
              // newValue是系統(tǒng)分配的變量名,內(nèi)部存儲(chǔ)著新值
              set {
                  self.averageScore = newValue
              }
          }
      }
    
      // 獲取計(jì)算屬性的值
      print(stu.averageScore)
    
類屬性
  • 類屬性是與類相關(guān)聯(lián)的,而不是與類的實(shí)例相關(guān)聯(lián)

  • 所有的類和實(shí)例都共有一份類屬性.因此在某一處修改之后,該類屬性就會(huì)被修改

  • 類屬性的設(shè)置和修改,需要通過(guò)類來(lái)完成

  • 下面是類屬性的寫(xiě)法

    • 類屬性使用static來(lái)修飾
    • courseCount是類屬性,用來(lái)記錄學(xué)生有多少門(mén)課程
      class Student : NSObject {
          // 定義屬性
          // 存儲(chǔ)屬性
          var age : Int = 0
          var name : String?
          
          var chineseScore : Double = 0.0
          var mathScore : Double = 0.0
          
          // 計(jì)算屬性
          var averageScore : Double {
              get {
                  return (chineseScore + mathScore) / 2
              }
          
              // 沒(méi)有意義.newValue是系統(tǒng)分配的變量名,內(nèi)部存儲(chǔ)著新值
              set {
                  self.averageScore = newValue
              }
          }
          
          // 類屬性
          static var corseCount : Int = 0
      }
    
      // 設(shè)置類屬性的值
      Student.corseCount = 3
      // 取出類屬性的值
      print(Student.corseCount)
    
監(jiān)聽(tīng)屬性的改變
  • 在OC中我們可以重寫(xiě)set方法來(lái)監(jiān)聽(tīng)屬性的改變

  • Swift中可以通過(guò)屬性觀察者來(lái)監(jiān)聽(tīng)和響應(yīng)屬性值的變化

  • 通常是監(jiān)聽(tīng)存儲(chǔ)屬性和類屬性的改變.(對(duì)于計(jì)算屬性,我們不需要定義屬性觀察者,因?yàn)槲覀兛梢栽谟?jì)算屬性的setter中直接觀察并響應(yīng)這種值的變化)

  • 我們通過(guò)設(shè)置以下觀察方法來(lái)定義觀察者

    • willSet:在屬性值被存儲(chǔ)之前設(shè)置。此時(shí)新屬性值作為一個(gè)常量參數(shù)被傳入。該參數(shù)名默認(rèn)為newValue,我們可以自己定義該參數(shù)名
    • didSet:在新屬性值被存儲(chǔ)后立即調(diào)用。與willSet相同,此時(shí)傳入的是屬性的舊值,默認(rèn)參數(shù)名為oldValue
    • willSet與didSet只有在屬性第一次被設(shè)置時(shí)才會(huì)調(diào)用,在初始化時(shí),不會(huì)去調(diào)用這些監(jiān)聽(tīng)方法
  • 監(jiān)聽(tīng)的方式如下:

    • 監(jiān)聽(tīng)age和name的變化
      class Person : NSObject {
          var name : String? {
              // 可以給newValue自定義名稱
              willSet (new){ // 屬性即將改變,還未改變時(shí)會(huì)調(diào)用的方法
                  // 在該方法中有一個(gè)默認(rèn)的系統(tǒng)屬性newValue,用于存儲(chǔ)新值
                  print(name)
                  print(new)
              }
              // 可以給oldValue自定義名稱
              didSet (old) { // 屬性值已經(jīng)改變了,會(huì)調(diào)用的方法
                  // 在該方法中有一個(gè)默認(rèn)的系統(tǒng)屬性oldValue,用于存儲(chǔ)舊值
                  print(name)
                  print(old)
              }
          }
          var age : Int = 0
          var height : Double = 0.0
      }
    
      let p : Person = Person()
    
      // 在賦值時(shí),監(jiān)聽(tīng)該屬性的改變
      // 在OC中是通過(guò)重寫(xiě)set方法
      // 在swift中,可以給屬性添加監(jiān)聽(tīng)器
      p.name = "why"
    
      //p.name = "yz"
    

類的構(gòu)造函數(shù)

構(gòu)造函數(shù)的介紹

  • 構(gòu)造函數(shù)類似于OC中的初始化方法:init方法
  • 默認(rèn)情況下載創(chuàng)建一個(gè)類時(shí),必然會(huì)調(diào)用一個(gè)構(gòu)造函數(shù)
  • 即便是沒(méi)有編寫(xiě)任何構(gòu)造函數(shù),編譯器也會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù)。
  • 如果是繼承自NSObject,可以對(duì)父類的構(gòu)造函數(shù)進(jìn)行重寫(xiě)

構(gòu)造函數(shù)的基本使用

構(gòu)造函數(shù)的基本使用
  • 類的屬性必須有值

  • 如果不是在定義時(shí)初始化值,可以在構(gòu)造函數(shù)中賦值

      class Person: NSObject {
          var name : String
          var age : Int
      
          // 重寫(xiě)了NSObject(父類)的構(gòu)造方法
          override init() {
              name = ""
              age = 0
          }
      }
      
      // 創(chuàng)建一個(gè)Person對(duì)象
      let p = Person()
    
初始化時(shí)給屬性賦值
  • 很多時(shí)候,我們?cè)趧?chuàng)建一個(gè)對(duì)象時(shí)就會(huì)給屬性賦值

  • 可以自定義構(gòu)造函數(shù)

  • 注意:如果自定義了構(gòu)造函數(shù),會(huì)覆蓋init()方法.即不在有默認(rèn)的構(gòu)造函數(shù)

      class Person: NSObject {
          var name : String
          var age : Int
      
          // 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
          init(name : String, age : Int) {
              self.name = name
              self.age = age
          }
      }
      
      // 創(chuàng)建一個(gè)Person對(duì)象
      let p = Person(name: "why", age: 18)
    
字典轉(zhuǎn)模型(初始化時(shí)傳入字典)
  • 真實(shí)創(chuàng)建對(duì)象時(shí),更多的是將字典轉(zhuǎn)成模型

  • 注意:

    • 去字典中取出的是NSObject,任意類型.
    • 可以通過(guò)as!轉(zhuǎn)成需要的類型,再賦值(不可以直接賦值)
      class Person: NSObject {
          var name : String
          var age : Int
          
          // 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
          init(dict : [String : NSObject]) {
              name = dict["name"] as! String
              age = dict["age"] as! Int
          }
      }
    
      // 創(chuàng)建一個(gè)Person對(duì)象
      let dict = ["name" : "why", "age" : 18]
      let p = Person(dict: dict)
    
字典轉(zhuǎn)模型(利用KVC轉(zhuǎn)化)
  • 利用KVC字典轉(zhuǎn)模型會(huì)更加方便

  • 注意:

    • KVC并不能保證會(huì)給所有的屬性賦值
    • 因此屬性需要有默認(rèn)值
      • 基本數(shù)據(jù)類型默認(rèn)值設(shè)置為0
      • 對(duì)象或者結(jié)構(gòu)體類型定義為可選類型即可(可選類型沒(méi)有賦值前為nil)
        class Person: NSObject {
            // 結(jié)構(gòu)體或者類的類型,必須是可選類型.因?yàn)椴荒鼙WC一定會(huì)賦值
            var name : String?
            
            // 基本數(shù)據(jù)類型不能是可選類型,否則KVC無(wú)法轉(zhuǎn)化
            var age : Int = 0
            
            // 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
            init(dict : [String : NSObject]) {
                // 必須先初始化對(duì)象
                super.init()
            
                // 調(diào)用對(duì)象的KVC方法字典轉(zhuǎn)模型
                setValuesForKeysWithDictionary(dict)
            }
        }
    
        // 創(chuàng)建一個(gè)Person對(duì)象
        let dict = ["name" : "why", "age" : 18]
        let p = Person(dict: dict)
    

類的析構(gòu)函數(shù)

析構(gòu)函數(shù)

  • Swift 會(huì)自動(dòng)釋放不再需要的實(shí)例以釋放資源

    • Swift 通過(guò)自動(dòng)引用計(jì)數(shù)(ARC)處理實(shí)例的內(nèi)存管理
    • 當(dāng)引用計(jì)數(shù)為0時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)(不可以手動(dòng)調(diào)用)
    • 通常在析構(gòu)函數(shù)中釋放一些資源(如移除通知等操作)
  • 析構(gòu)函數(shù)的寫(xiě)法

      deinit {
          // 執(zhí)行析構(gòu)過(guò)程
      }
    

示例練習(xí)

    class Person {
        var name : String
        var age : Int
    
        init(name : String, age : Int) {
            self.name = name
            self.age = age
        }
    
        deinit {
            print("Person-deinit")
        }
    }
    
    var p : Person? = Person(name: "why", age: 18)
    p = nil

自動(dòng)引用計(jì)數(shù)

工作機(jī)制

  • Swift和OC一樣,采用自動(dòng)引用計(jì)數(shù)來(lái)管理內(nèi)容
    • 當(dāng)有一個(gè)強(qiáng)引用指向某一個(gè)動(dòng)向時(shí),該對(duì)象的引用計(jì)數(shù)會(huì)自動(dòng)+1
    • 當(dāng)該強(qiáng)引用消失時(shí),引用計(jì)數(shù)會(huì)自動(dòng)-1
    • 當(dāng)引用計(jì)數(shù)為0時(shí),該對(duì)象會(huì)被銷毀

循環(huán)引用

  • 在通常情況下,ARC是會(huì)自動(dòng)幫助我們管理內(nèi)存的

  • 但是在開(kāi)發(fā)中我們經(jīng)常會(huì)出現(xiàn)循環(huán)引用的問(wèn)題,比如下面的示例

    • Student對(duì)Book對(duì)象有一個(gè)強(qiáng)引用
    • 而B(niǎo)ook對(duì)Student有一個(gè)強(qiáng)引用
    • 在兩個(gè)對(duì)象都指向nil時(shí),依然不會(huì)被銷毀,就形成了循環(huán)引用
      // 1.創(chuàng)建類
      class Student {
          var book : Book?
    
          deinit {
              print("Student -- deinit")
          }
      }
    
      class Book {
          var owner : Student?
    
          deinit {
              print("Book -- deinit")
          }
      }
    
      // 2.創(chuàng)建對(duì)象
      var stu : Student? = Student()
      var book : Book? = Book()
    
      // 3.相互引用
      stu?.book = book
      book?.owner = stu
    
      // 4.對(duì)象置nil
      stu = nil
      book = nil
    
  • 解決方案

    • swift提供了兩種解決方案
      • weak : 和OC中的__weak一樣是一個(gè)弱引用.當(dāng)指向的對(duì)象銷毀時(shí),會(huì)自動(dòng)將指針指向nil
      • unowned : 和OC中的__unsafe_unretained.當(dāng)對(duì)象銷毀時(shí)依然指向原來(lái)的位置(容易引起野指針)
      // 1.創(chuàng)建類
      class Student {
          weak var book : Book?
          // unowned var book : Book = Book()
          
          deinit {
              print("Student -- deinit")
          }
      }
    
      class Book {
          var owner : Student?
    
          deinit {
              print("Book -- deinit")
          }
      }
    
      // 2.創(chuàng)建對(duì)象
      var stu : Student? = Student()
      var book : Book? = Book()
    
      // 3.相互引用
      stu?.book = book!
      book?.owner = stu
    
      // 4.對(duì)象置nil
      stu = nil
      book = nil
    

可選鏈

可選連的概念

  • 它的可選性體現(xiàn)于請(qǐng)求或調(diào)用的目標(biāo)當(dāng)前可能為空(nil)
    • 如果可選的目標(biāo)有值,那么調(diào)用就會(huì)成功;
    • 如果選擇的目標(biāo)為空(nil),則這種調(diào)用將返回空(nil)
  • 多次調(diào)用被鏈接在一起形成一個(gè)鏈,如果任何一個(gè)節(jié)點(diǎn)為空(nil)將導(dǎo)致整個(gè)鏈?zhǔn)А?/li>
  • 可選鏈的使用
    • 在可選類型后面放一個(gè)問(wèn)號(hào),可以定義一個(gè)可選鏈。
    • 這一點(diǎn)很像在可選值后面放一個(gè)嘆號(hào)來(lái)強(qiáng)制拆得其封包內(nèi)的值
      • 它們的主要的區(qū)別在于當(dāng)可選值為空時(shí)可選鏈即刻失敗
      • 然而一般的強(qiáng)制解析將會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤。
    • 因?yàn)榭蛇x鏈的結(jié)果可能為nil,可能有值.因此它的返回值是一個(gè)可選類型.
      • 可以通過(guò)判斷返回是否有值來(lái)判斷是否調(diào)用成功
      • 有值,說(shuō)明調(diào)用成功
      • 為nil,說(shuō)明調(diào)用失敗

可選鏈的示例

  • 從可選鏈中取值

    • 示例描述: 人(Person)有一個(gè)狗(Dog),狗(Dog)有一個(gè)玩具(Toy),玩具有價(jià)格(price)
    • 使用代碼描述上述信息
      // 1.定義類
      class Person {
          var name : String
          var dog : Dog?
          
          init(name : String) {
              self.name = name
          }
      }
    
      class Dog {
          var color : UIColor
          var toy : Toy?
          
          init(color : UIColor) {
              self.color = color
          }
          
          func runing() {
              print("跑起來(lái)")
          }
      }
    
      class Toy {
          var price : Double = 0.0
      }
    
      // 2.創(chuàng)建對(duì)象,并且設(shè)置對(duì)象之間的關(guān)系
      // 2.1.創(chuàng)建對(duì)象
      let person = Person(name: "小明")
      let dog = Dog(color: UIColor.yellowColor())
      let toy = Toy()
      toy.price = 100.0
    
      // 2.2.設(shè)置對(duì)象之間的關(guān)系
      person.dog = dog
      dog.toy = toy
    
  • 需求:獲取小明的大黃寵物的玩具價(jià)格取出的值為可選類型,因?yàn)榭蛇x鏈中有一個(gè)可選類型為nil,則返回nil因此結(jié)果可能有值,可能為nil.因此是一個(gè)可選類型

      let price = person.dog?.toy?.price
      print(price) // Optional(100.0)\n
    
  • 需求:給小明的大黃一個(gè)新的玩具

    • 相當(dāng)于給可選類型賦值
      person.dog?.toy = Toy()
    
  • 需求:讓小明的狗跑起來(lái)

    • 如果可選類型有值,則會(huì)執(zhí)行該方法
    • 如果可選類型為nil,則該方法不會(huì)執(zhí)行
      person.dog?.runing()
    

協(xié)議

協(xié)議的格式

  • 協(xié)議的定義方式與類,結(jié)構(gòu)體,枚舉的定義都非常相似

      protocol SomeProtocol {
          // 協(xié)議方法
      }
    
  • 遵守協(xié)議的格式

      class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
        // 類的內(nèi)容
        // 實(shí)現(xiàn)協(xié)議中的方法
      }
    

協(xié)議的基本使用

  • 定義協(xié)議和遵守協(xié)議

      // 1.定義協(xié)議
      protocol SportProtocol {
          func playBasketball()
          func playFootball()
      }
      
      // 2.遵守協(xié)議
      // 注意:默認(rèn)情況下在swift中所有的協(xié)議方法都是必須實(shí)現(xiàn)的,如果不實(shí)現(xiàn),則編譯器會(huì)報(bào)錯(cuò)
      class Person : SportProtocol {
          var name : String?
          var age : Int = 0
      
          // 實(shí)現(xiàn)協(xié)議中的方法
          func playBasketball() {
              print("人在打籃球")
          }
      
          func playFootball() {
              print("人在踢足球")
          }
      }
    
  • 協(xié)議之間的繼承

      protocol CrazySportProtocol {
          func jumping()
      }
      
      protocol SportProtocol : CrazySportProtocol {
          func playBasketball()
          func playFootball()
      }
    

代理設(shè)計(jì)模式

  • 協(xié)議繼承用于代理設(shè)計(jì)模式

      protocol BuyTicketProtocol {
          func buyTicket()
      }
      
      class Person {
          // 1.定義協(xié)議屬性
          var delegate : BuyTicketProtocol
      
          // 2.自定義構(gòu)造函數(shù)
          init (delegate : BuyTicketProtocol) {
              self.delegate = delegate
          }
      
          // 3.行為
          func goToBeijing() {
              delegate.buyTicket()
          }
      }
    
      class HuangNiu: BuyTicketProtocol {
          func buyTicket() {
              print("買(mǎi)了一張火車票")
          }
      }
      
      let p = Person(delegate: HuangNiu())
      p.goToBeijing()
    ?```
    

協(xié)議中方法的可選

    // 1.定義協(xié)議
    @objc
    protocol SportProtocol {
        func playBasketball()
    
        optional func playFootball()
    }
    
    // 2.遵守協(xié)議
    class Person : SportProtocol {
        var name : String?
        var age : Int = 0
    
        // 實(shí)現(xiàn)協(xié)議中的方法
        @objc func playBasketball() {
            print("人在打籃球")
        }
    }

閉包

閉包的介紹

  • 閉包和OC中的block非常相似
    • OC中的block是匿名的函數(shù)
    • Swift中的閉包是一個(gè)特殊的函數(shù)
    • block和閉包都經(jīng)常用于回調(diào)
  • 注意:閉包和block一樣,第一次使用時(shí)可能不習(xí)慣它的語(yǔ)法,可以先按照使用簡(jiǎn)單的閉包,隨著學(xué)習(xí)的深入,慢慢掌握其靈活的運(yùn)用方法.

閉包的使用

block的用法回顧
  • 定義網(wǎng)絡(luò)請(qǐng)求的類

      @interface HttpTool : NSObject
      - (void)loadRequest:(void (^)())callBackBlock;
      @end
      
      @implementation HttpTool
      - (void)loadRequest:(void (^)())callBackBlock
      {
          dispatch_async(dispatch_get_global_queue(0, 0), ^{
              NSLog(@"加載網(wǎng)絡(luò)數(shù)據(jù):%@", [NSThread currentThread]);
      
              dispatch_async(dispatch_get_main_queue(), ^{
                  callBackBlock();
              });
          });
      }
      @end
    
  • 進(jìn)行網(wǎng)絡(luò)請(qǐng)求,請(qǐng)求到數(shù)據(jù)后利用block進(jìn)行回調(diào)

      - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
      {
          [self.httpTool loadRequest:^{
              NSLog(@"主線程中,將數(shù)據(jù)回調(diào).%@", [NSThread currentThread]);
          }];
      }
    
  • block寫(xiě)法總結(jié):

    block的寫(xiě)法:
    類型:
    返回值(^block的名稱)(block的參數(shù))
    
    值:
    ^(參數(shù)列表) {
        // 執(zhí)行的代碼
    };
    
使用閉包代替block
  • 定義網(wǎng)絡(luò)請(qǐng)求的類

      class HttpTool: NSObject {
    
          func loadRequest(callBack : ()->()){
              dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
                  print("加載數(shù)據(jù)", [NSThread.currentThread()])
      
                   dispatch_async(dispatch_get_main_queue(), { () -> Void in
                      callBack()
                   })
              }
          }
      }
    
  • 進(jìn)行網(wǎng)絡(luò)請(qǐng)求,請(qǐng)求到數(shù)據(jù)后利用閉包進(jìn)行回調(diào)

        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            // 網(wǎng)絡(luò)請(qǐng)求
            httpTool.loadRequest ({ () -> () in
                print("回到主線程", NSThread.currentThread());
            })
        }
    
  • 閉包寫(xiě)法總結(jié):

      閉包的寫(xiě)法:
          類型:(形參列表)->(返回值)
          技巧:初學(xué)者定義閉包類型,直接寫(xiě)()->().再填充參數(shù)和返回值
      
          值:
          {
              (形參) -> 返回值類型 in
              // 執(zhí)行代碼
          }
    
閉包的簡(jiǎn)寫(xiě)
  • 如果閉包沒(méi)有參數(shù),沒(méi)有返回值.in和in之前的內(nèi)容可以省略

        httpTool.loadRequest({
            print("回到主線程", NSThread.currentThread());
        })
    
  • 尾隨閉包寫(xiě)法:

    • 如果閉包是函數(shù)的最后一個(gè)參數(shù),則可以將閉包寫(xiě)在()后面
    • 如果函數(shù)只有一個(gè)參數(shù),并且這個(gè)參數(shù)是閉包,那么()可以不寫(xiě)
        httpTool.loadRequest() {
            print("回到主線程", NSThread.currentThread());
        }
    
        // 開(kāi)發(fā)中建議該寫(xiě)法
        httpTool.loadRequest {
            print("回到主線程", NSThread.currentThread());
        }
    

閉包的循環(huán)引用

  • 如果在HttpTool中有對(duì)閉包進(jìn)行強(qiáng)引用,則會(huì)形成循環(huán)引用

  • 補(bǔ)充:在Swift中檢測(cè)一個(gè)對(duì)象是否銷毀,可以實(shí)現(xiàn)對(duì)象的deinit函數(shù)

        // 析構(gòu)函數(shù)(相當(dāng)于OC中dealloc方法)
        deinit {
            print("ViewController----deinit")
        }
    
  • 循環(huán)引用的(實(shí)現(xiàn))

    • 該實(shí)現(xiàn)是為了產(chǎn)生循環(huán)引用,而產(chǎn)生的循環(huán)引用
      class HttpTool: NSObject {
    
          // 定義屬性,來(lái)強(qiáng)引用傳入的閉包
          var callBack : (()->())?
          
          func loadRequest(callBack : ()->()){
              dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
                  print("加載數(shù)據(jù)", [NSThread.currentThread()])
          
                   dispatch_async(dispatch_get_main_queue(), { () -> Void in
                      callBack()
                   })
              }
          
              self.callBack = callBack
          }
      }
    
  • swift中解決循環(huán)引用的方式

  • 方案一:

    • 使用weak,對(duì)當(dāng)前控制器使用弱引用
    • 但是因?yàn)閟elf可能有值也可能沒(méi)有值,因此weakSelf是一個(gè)可選類型,在真正使用時(shí)可以對(duì)其強(qiáng)制解包(該處強(qiáng)制解包沒(méi)有問(wèn)題,因?yàn)榭刂破饕欢ù嬖?否則無(wú)法調(diào)用所在函數(shù))
        // 解決方案一:
        weak var weakSelf = self
        httpTool.loadData {
            print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
            weakSelf!.view.backgroundColor = UIColor.redColor()
        }
    
  • 方案二:

    • 和方案一類型,只是書(shū)寫(xiě)方式更加簡(jiǎn)單
    • 可以寫(xiě)在閉包中,并且在閉包中用到的self都是弱引用
        httpTool.loadData {[weak self] () -> () in
            print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
            self!.view.backgroundColor = UIColor.redColor()
        }
    
  • 方案三:(常用)

    • 使用關(guān)鍵字unowned
    • 從行為上來(lái)說(shuō) unowned 更像OC中的 unsafe_unretained
    • unowned 表示:即使它原來(lái)引用的對(duì)象被釋放了,仍然會(huì)保持對(duì)被已經(jīng)釋放了的對(duì)象的一個(gè) "無(wú)效的" 引用,它不能是 Optional 值,也不會(huì)被指向 nil
      httpTool.loadData {[unowned self] () -> () in
              print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
              self.view.backgroundColor = UIColor.redColor()
          }
    

懶加載

懶加載的介紹

  • swift中也有懶加載的方式
    • (蘋(píng)果的設(shè)計(jì)思想:希望所有的對(duì)象在使用時(shí)才真正加載到內(nèi)存中)
  • 和OC不同的是swift有專門(mén)的關(guān)鍵字來(lái)實(shí)現(xiàn)懶加載
  • lazy關(guān)鍵字可以用于定義某一個(gè)屬性懶加載

懶加載的使用

  • 格式

      lazy var 變量: 類型 = { 創(chuàng)建變量代碼 }()
    
  • 懶加載的使用

        // 懶加載的本質(zhì)是,在第一次使用的時(shí)候執(zhí)行閉包,將閉包的返回值賦值給屬性
        // lazy的作用是只會(huì)賦值一次
        lazy var array : [String] = {
            () -> [String] in
            return ["why", "lmj", "lnj"]
        }()
    

常見(jiàn)注釋

單行注釋

  • Swift 中的注釋與C 語(yǔ)言的注釋非常相似。

  • 單行注釋以雙正斜杠(//)作為起始標(biāo)記

      // 注釋內(nèi)容
    

多行注釋

  • 其起始標(biāo)記為單個(gè)正斜杠后跟隨一個(gè)星號(hào)(/*)

  • 終止標(biāo)記為一個(gè)星號(hào)后跟隨單個(gè)正斜杠(*/)

      /* 這是一個(gè),
      多行注釋 */
    
  • 和與 C 語(yǔ)言多行注釋不同,Swift 的多行注釋可以嵌套在其它的多行注釋之中

      /* 這是第一個(gè)多行注釋的開(kāi)頭
      /* 這是第二個(gè)被嵌套的多行注釋 */
      這是第一個(gè)多行注釋的結(jié)尾 */
    

文檔注釋

  • Swift中添加文檔注釋較為簡(jiǎn)單

  • 使用(///)可以為方法或者屬性添加文檔注釋

      /// 打電話給某人
      func callPhone(phoneNum : String) {
          print("打電話給\(phoneNum)")
      }
    

分組注釋

  • swift中不可以再使用 #pragma mark -

  • 如果打算對(duì)代碼進(jìn)行分組可以使用 // MARK:-方式

      // MARK:-
    

訪問(wèn)權(quán)限

swift中的訪問(wèn)權(quán)限

  • Swift 中的訪問(wèn)控制模型基于模塊和源文件這兩個(gè)概念

    - internal : 在本模塊中都可以進(jìn)行訪問(wèn)
    - private : 在當(dāng)前源文件中可以訪問(wèn)
    - public : 在其他模塊中可以訪問(wèn)
    

異常處理

異常的介紹

  • 只要我們?cè)诰幊?,就一定要面?duì)錯(cuò)誤處理的問(wèn)題。
  • Swift在設(shè)計(jì)的時(shí)候就盡可能讓我們明確感知錯(cuò)誤,明確處理錯(cuò)誤
    • 比如:只有使用Optional才能處理空值;
  • 如何描述一個(gè)錯(cuò)誤?
    • 在Swift里,任何一個(gè)遵從ErrorType protocol的類型,都可以用于描述錯(cuò)誤。
    • ErrorType是一個(gè)空的protocol,它唯一的功能,就是告訴Swift編譯器,某個(gè)類型用來(lái)表示一個(gè)錯(cuò)誤。
    • 通常,我們使用一個(gè)enum來(lái)定義各種錯(cuò)誤的可能性

異常的示例

  • 假如我們想要讀取一個(gè)文件中的內(nèi)容,按照OC的邏輯我們可以這樣來(lái)模擬

    • 當(dāng)我們調(diào)用方法獲取結(jié)果為nil時(shí),你并不能確定到底參數(shù)了什么錯(cuò)誤得到了nil
      func readFileContent(filePath : String) -> String? {
          // 1.filePath為""
          if filePath == "" {
              return nil
          }
          
          // 2.filepath有值,但是沒(méi)有對(duì)應(yīng)的文件
          if filePath != "/User/Desktop/123.plist" {
              return nil
          }
          
          // 3.取出其中的內(nèi)容
          return "123"
      }
    
      readFileContent("abc")
    
  • 使用異常對(duì)上述方法進(jìn)行改進(jìn)

      // 1.定義異常
      enum FileReadError : ErrorType {
          case FileISNull
          case FileNotFound
      }
      
      // 2.改進(jìn)方法,讓方法拋出異常
      func readFileContent(filePath : String) throws -> String {
          // 1.filePath為""
          if filePath == "" {
      
              throw FileReadError.FileISNull
          }
      
          // 2.filepath有值,但是沒(méi)有對(duì)應(yīng)的文件
          if filePath != "/User/Desktop/123.plist" {
      
              throw FileReadError.FileISNull
          }
      
          // 3.取出其中的內(nèi)容
          return "123"
      }
    
  • 處理異常有三種方式

      // 3.異常的處理三種方式
      // 3.1.try方式,需要手動(dòng)處理異常
      do {
          let result = try readFileContent("abc")
      } catch {
          print(error)
      }
      
      // 3.2.try?方式,不處理異常,如果出現(xiàn)了異常,則返回一個(gè)nil.沒(méi)有異常,則返回對(duì)應(yīng)的值
      // 最終返回結(jié)果為一個(gè)可選類型
      let result = try? readFileContent("abc")
      
      // 3.3.try!方法,告訴系統(tǒng)該方法沒(méi)有異常.
      // 注意:如果出現(xiàn)了異常,則程序會(huì)崩潰
      try! readFileContent("abc")
    

Swift和OC相互調(diào)?用

Swift調(diào)?用OC

  1. 創(chuàng)建橋接?文件—> .h
  2. 在橋接?文件中導(dǎo)?入頭?文件
  3. 配置橋接?文件: 項(xiàng)目->buildSettings —> bridging —> 配置

OC調(diào)?用Swift

  • 項(xiàng)?目名字不能隨便起
  • Swift中的類/屬性/?方法必須使?用public修飾
  • 導(dǎo)?項(xiàng)目名稱-Swift.h
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容