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) ?
- 快速、現(xiàn)代、安全、互動,而且明顯優(yōu)于
Objective-C
語言;
- 取消了
Objective-C
的指針及其他不安全訪問的使用; - 舍棄
Objective C
早期應(yīng)用Smalltalk
的語法,全面改為 句點(diǎn)表示法; - 提供了類似 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
類型
- 小數(shù)默認(rèn)是
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)...該吃飯啦。。。