iOS開發(fā)之Swift基本語法詳解

Swift語言簡介

2010 年 7 月,蘋果開發(fā)者工具部門總監(jiān) Chris Lattner(克里斯·拉特納)開始著手Swift 編程語言的設(shè)計(jì)工作,用時(shí)一年時(shí)間,完成開發(fā)語言基本架構(gòu),經(jīng)歷了4年的開發(fā)周期,終于在2014 年 6 月Apple WWDC 發(fā)表,用來撰寫 OS X 和 iOS 應(yīng)用程序等。

Swift較Objective-C優(yōu)點(diǎn) ?

  1. 快速、現(xiàn)代、安全、互動,而且明顯優(yōu)于 Objective-C語言;
  1. 取消了 Objective-C 的指針及其他不安全訪問的使用;
  2. 舍棄 Objective C 早期應(yīng)用Smalltalk的語法,全面改為 句點(diǎn)表示法;
  3. 提供了類似 Java 的命名空間(namespace)、泛型(generic)、運(yùn)算對象重載(operator overloading)等新概念。

基本知識點(diǎn)詳解


常量與變量
  • let聲明常量,var聲明變量,打印print()
  • 枚舉類型:枚舉名稱點(diǎn)枚舉值(點(diǎn)語法表示)
  • 常量、變量可用任何字符表示,常量必須在定義時(shí)初始化, 否則會報(bào)錯(cuò)
  • 每行語句后不需添加分號(添加也正確),若是多條語句則需添加分號區(qū)別
  • 若在定義的同時(shí)并初始化 - 沒有必要指定數(shù)據(jù)類型,若定義時(shí)沒初始化 - 必須指定數(shù)據(jù)類型
  • 常量、變量名不能包含數(shù)學(xué)符號、箭頭、保留的/非法的Unicode 碼位、連線與制表符、也不能以數(shù)字開頭,但可在常量、變量名其他地方包含數(shù)字
  • Swift對數(shù)據(jù)類型要求非常嚴(yán)格,若要轉(zhuǎn)換,則必須顯示轉(zhuǎn)換;
    • 小數(shù)默認(rèn)是Double類型
    • 整數(shù)默認(rèn)是Int類型
var 2x = 50   //錯(cuò)誤
var ?? = 100 
var 歡迎 = 500
let num:Int = 10 //顯示指定類型
let sum = num + Int(num2) //顯示轉(zhuǎn)換(不存在隱式轉(zhuǎn)換)
邏輯分支
  • if語句不存在“非零即真”概念 條件只能放BOOL值/(true、false)
  • 三目運(yùn)算符:可以if ... else 語句轉(zhuǎn)換而來,保持了和OC的一致
  • if語句條件的()可以省略,{ }不能省略
  • for循環(huán) for ... in ... { ... },0..<10 -> 0~9,0...10 ->0~10
for _ in 0..<10 {
    print("hello")  //_代表忽略
}

var a = 10
while a < 10 {
    print(a)
    a++ // ++ 前面的空格不能省略
}

//do~while在Swift2.0之后變?yōu)?repeat { ... } while(...), do用于捕捉異常
var b = 10
repeat{
print(b)
b++
}while b < 10
/**
*  switch 后面()可以省略 ,每條語句后面不需添加break,在case語句內(nèi)添加變量不需{}
* default語句必須放在最后,且大部分情況下不能省略
*/
switch num{
case 1:
    print("1")
case 10:
    print("10")
case 15:
    print("15")
    let value = 15
default:
    print("0")
}

//條件綁定
var point = (100, 10)
switch point{
    //只有where后面的條件表達(dá)式為真才賦值并執(zhí)行case后的語句
    case var(x, y) where x > y: 
        print("x= \(x) , y= \(y)")
    default:
        print("Other")
}

//值綁定
var point = (1, 10)
switch point{
    case (var x, 10): //會將point中X的值賦值給X
        print("x= \(x)")
    case (var x, var y): //會將point中X、Y的值賦值給X、Y
        print("x= \(x) y= \(y)")
    case var( x, y):
        print("x= \(x) y= \(y)")
    default:
        print("Other")
}

var point = (10, 15)
switch point{
    case (0, 0):
        print("坐標(biāo)在原點(diǎn)")
    case (1...10, 10...20): // 可在元祖中再加上區(qū)間
        print("坐標(biāo)的X和Y在1~10之間")
    case (_, 0): // X可以是任意數(shù)
        print("坐標(biāo)的X在X軸上")
    default:
        print("Other")
}

  • C語言和OC并沒有真正的Bool類型(類似非0即真),Swift引入了真正的Bool類型(Bool true false)
  • 元祖:將多個(gè)相同或者不同類型的值用一個(gè)小括號括起來,是復(fù)合類型, 小括號中可以寫任意類型
//有了元祖之后就可以實(shí)現(xiàn)讓一個(gè)函數(shù)返回多個(gè)值
let (name1 , age1 , _) =  ("chongzone", 50, 25) //利用_通配符來忽略提取
print(name1);print(age1)

//元祖的其它定義方式: 
let (name , age , score) =  ("chongzone",  50, 25)
print(name);print(age);print(score)

//指明應(yīng)用元祖元素的名稱
let student2 = (name:"chongzone",age:50,score:99)
print(student2.name);print(student2.age);print(student2.score)

let student = ("chongzone", 50, 55)
let student1: (String, Int, Double) = ("chongzone", 50, 55)
print(student);print(student.0);print(student.1);print(student.2)

  • 可選項(xiàng)(optional) - 直接打印可選類型,則會被optional包囊
  • 對于可選項(xiàng),可使用 來強(qiáng)制解析,若是可選項(xiàng)沒有值再做類型轉(zhuǎn)換,會導(dǎo)致程序崩潰
  • 解決辦法 - 可選綁定 - let + 常量 = 可選項(xiàng)
  • ??是一個(gè)非常有用的操作符,能夠快速對nil進(jìn)行判斷,若對象是 nil,則使用 ?? 后面的值代替前面的 nil 值參與計(jì)算,在使用?? 時(shí),前面的整個(gè)部分需要使用 () 包裝
let url = NSURL(string: "www.baidu.com")
let request = NSURLRequest(URL: url!)
//解決辦法 - 可選綁定
if let urlNormal = url {
    print(urlNormal)
    let request = NSURLRequest(URL: urlNormal)
}

  • 數(shù)組、字典、字符串
//定義數(shù)組時(shí)若指定保存對象的類型,則不能向數(shù)組添加其他類型內(nèi)容
let arr = ["1","2"]
var arr2 : [String]  //或是 var arr2 = [String]() //只能保存字符串對象
arr2 = ["1"]
arr2.append("2")

var dict = ["name":"chong","age":25]
//利用元祖類型遍歷字典,則會將字典內(nèi)的key賦值給元祖中第一個(gè)變量,字典的value賦值給元祖中第二個(gè)變量
for (key, value) in dict {
    print(k)
    print(v)
}

//合并字典
var dict2 = ["sex":"man"]
for (k, v) in dict2 {
    dict[k] = v
}

//格式化字符串
let name = "chong"
let age = 10
var str4 = "name = \(name),age = \(age)"
var str5 = String(format: "%@, %04d", arguments: [name, age])

////遍歷字符串 可直接遍歷
var str6 = "chongzone is 25 la"
for st in str6.characters {
    print(st)
}

//截取 建議轉(zhuǎn)化OC操作
var str7 : NSString = "chong is 30 lo"
var str8 = "chong is 30 la" as NSString
var subStr = str7.substringWithRange(NSMakeRange(3, 10))

  • 函數(shù)(四種類型)
//沒參數(shù)沒返回值
func sum4() {
    print("hello")
}

//存在參數(shù)沒返回值
func sum2(a: Int, b: Int) {
    print(a + b)
}

//沒有參數(shù)與存在返回值
func sum3() -> Int {
    return 20
}

//存在參數(shù)與返回值
func sum(a: Int, b: Int) ->Int {
    return a + b
}

//對于存在的參數(shù),可以添加標(biāo)簽
func sum5 (one a: Int, two b: Int) ->Int {
    return a + b
}
print(sum5(one: 10, two: 10))

  • 閉包、函數(shù)
//Swift方法/函數(shù) 參數(shù)在前 類型在后
    /**
     *  閉包 類似于 block,閉包是定義函數(shù)的, Swift中函數(shù)就是一種特殊的閉包
     *  閉包的使用和block一樣, 用于保存一段代碼, 用作回調(diào), 用作執(zhí)行耗時(shí)操作
     *  定義閉包格式 -  閉包名:形參 -> 返回值類型
     *  調(diào)用閉包時(shí)格式:
     *  {
     *   (參數(shù)) -> 返回值類型
     *   in
     *   執(zhí)行語句
     *  }
    */

//閉包的返回值
//Swift 不建議使用self,不同數(shù)據(jù)類型不能參與計(jì)算
override func viewDidLoad() {
        super.viewDidLoad()
       //調(diào)用重構(gòu)后的函數(shù)
        let sc = createScrollView({ () -> Int in
            return 10
            }) { (index) -> UILabel in
                let width = 45
                let label = UILabel()
                label.backgroundColor = UIColor.greenColor()
                label.textColor = UIColor.darkGrayColor()
                label.font = UIFont.systemFontOfSize(17)
                label.text = "text\(index)"
                label.frame = CGRect(x: index * width, y: 0, width: width, height: 44)
              /**
                * 閉包內(nèi)部, 為了能夠準(zhǔn)確定位到view, 所以在閉包內(nèi)部代碼需要寫self
                * Swift開發(fā)中不建議寫self, 一般是在閉包內(nèi)才使用
                * "weakSelf!" 強(qiáng)制其存在 (weakSelf是可選類型 需要‘!’保證其一定不是nil)并且防止了其循環(huán)引用
                */
                weakSelf!.view.backgroundColor = UIColor.redColor()
                return label
        }
        view.addSubview(sc)
    }
    
    //2個(gè)參數(shù)都是閉包,定義閉包后一般都會在本函數(shù)內(nèi)部都會調(diào)用該閉包實(shí)現(xiàn)
    func createScrollView(labelCount: ()->Int, labelWithIndex: (index:Int)->UILabel) -> UIScrollView{
        // 1.創(chuàng)建UIScrollView
        let sc = UIScrollView(frame: CGRect(x: 0, y: 100, width: 375, height: 44))
        sc.backgroundColor = UIColor.orangeColor()
        //labelCount():調(diào)用外部實(shí)現(xiàn)的閉包代碼并返回int
        let count = labelCount()
        
        // 2.遍歷創(chuàng)建UILabel
        for i in 0..<count{
           //labelWithIndex(index: i):先調(diào)用外部實(shí)現(xiàn)的閉包代碼并返回UILabel
            let label = labelWithIndex(index: i)
            sc.addSubview(label)
            sc.contentSize = CGSize(width: CGFloat(count) * label.bounds.width, height: 44)
        }
        return sc
    }

  • 自定義構(gòu)造方法
//新建一個(gè)對象類
class Chongzone: NSObject {
    
    var name: String?
    var age: Int = 0

    /**
     * Swift要求屬性必須初始化,若定義屬性(“對象類型”)沒初始化,則需在后面加上 ?,若是“基本數(shù)據(jù)類型”,初始化最好直接賦值為0,因?yàn)閟uper.init()不會分配其存儲空間
     * 若在構(gòu)造方法中對屬性初始化,則不再需要 ?
     * 若要初始化必須重寫init方法, 重寫init方法后就不用加?號了
     * Swift中支持方法名重載, 同樣的方法名稱只要參數(shù)/返回值不同就可以
     * 若是自定義了init方法, 但沒重寫init方法, 默認(rèn)init方法就會失效
     */
     
    //默認(rèn)init方法
    override init() {
        name = "chongzone"
        age = 26
    }
    
    //自定義的構(gòu)造方法
    init(name:String, age:Int) {
        self.name = name
        self.age = age
    }
    
    init(dict: [String: NSObject]) {
        // 使用kvc給self賦值之前, 必須調(diào)用super.init(分配其內(nèi)存空間)
        super.init()
        self.setValuesForKeysWithDictionary(dict)
    }
}


//對應(yīng)控制器調(diào)用
override func viewDidLoad() {
        super.viewDidLoad()
        // 不需import來導(dǎo)入某個(gè)類/控制器可直接使用, 因?yàn)镾wift中有一個(gè)命名空間(namespace(默認(rèn)情況下項(xiàng)目名稱))的概念,同一個(gè)項(xiàng)目所有的資源共享
        // 使用Swift最好使用cocoapods管理三方框架, 避免命名空間相同導(dǎo)致的沖突
        
        //則對應(yīng)的三種初始化方法
        let cz = Chongzone()
        print("\(cz.name), \(cz.age)")
        
        let cz2 = Chongzone(name: "chongzone", age: 26)
        print("\(cz2.name), \(cz2.age)")
        
        let cz3 = Chongzone(dict: ["name": "chongzone", "age": 26])
        print("\(cz3.name), \(cz3.age)")
    }

  • 懶加載(lazy)本質(zhì)上是定義并執(zhí)行一個(gè)閉包
// lazy var  變量:類型 = { ... }()
lazy var dataList: [String] = {
        print("...")
        return ["chongzone", "kongjian", "jianshu"]
    }()

  • getter、setter方法
class Chongzone: NSObject {
    var title:String? {
        didSet{
           title = title! + " happy"  //給屬性設(shè)置完值之后調(diào)用, 用于更新UI
        }
    }
    
    /**
    *  如果只重寫了get,沒有set. 那么屬性是一個(gè)"計(jì)算型"屬性
    *  計(jì)算型屬性不占用存儲空間, 相當(dāng)于OC中的readOnly 最后的 ?不需寫
    */
    var name2:String{
        return "chongzone"
    }
    
    //給某個(gè)變量賦值之后,去做些額外操作,賦值length - tomeStr改變
    var length: Int? {
    didSet {
        timeStr = String(format: "%02d:%02d:%02d", arguments:  [length! / 3600, (length! % 3600) / 60, length! % 60])
          }
      }
    var timeStr: String?

    // 以下開發(fā)中幾乎不用
    var _name:String?
    var name:String?{
        get{
            return _name
        }
        set{
           _name = newValue //只要外界給name賦值,則會保存在newValue
        }
    }
}

//對應(yīng)的控制器
override func viewDidLoad() {
        super.viewDidLoad()
        let cz  = Chongzone()
        print(cz.name2) //chongzone
        
        cz.title = " hello" //賦值后調(diào)用 didSet
        print(cz.title!) //hello happy 
    }

  • 部分代碼
//設(shè)置跟控制器,和OC同
window = UIWindow(frame: UIScreen.mainScreen().bounds)
        window?.backgroundColor = UIColor.whiteColor()
        window?.rootViewController = ViewController()
        window?.makeKeyAndVisible()

//按鈕觸發(fā)方法 action - 字符串""
 btn.addTarget(self, action: "btnClick:", forControlEvents: UIControlEvents.TouchUpInside)

//對應(yīng)的方法
func btnClick(btn: UIButton) {
        print(__FUNCTION__)
    }

  • 析構(gòu)函數(shù)
deinit {  //類似dealloc
    print("...")
}

  • 最后附上一段Swift環(huán)境下UITableView的簡單實(shí)現(xiàn)
//核心代碼
class ViewController: UIViewController {

    override func loadView() {
        let tableView = UITableView(frame: UIScreen.mainScreen().bounds)
        tableView.dataSource = self
        tableView.delegate = self
        view = tableView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    lazy var dataList : [String] = {
        return ["1","2","3"]
        }()
}

//MARK: - UITableViewDataSource
//Swift遵守協(xié)議 直接在后面添加 ,
//官方建議 數(shù)據(jù)源、代理單獨(dú)寫在一個(gè)擴(kuò)展(extension)
extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataList.count;
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier")
        if cell == nil {
            cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cellIdentifier")
        }

        cell?.textLabel?.text = dataList[indexPath.row]

        return  cell!
    }
}

終于完了... 有什么不對的地方還望指正咯,這個(gè)點(diǎn)...該吃飯啦。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容