小明學(xué)Swift-01-基礎(chǔ)篇

簡介

Swift是蘋果公司推出的可用于開發(fā)Mac OS和iOS系統(tǒng)上的應(yīng)用的專用編程語言妹笆,它相比于Objective-C(以下簡稱OC)語言佣盒,更加嚴(yán)謹(jǐn)官份,是一種強(qiáng)語言优妙。


使用工具

首先,先介紹使用的工具符隙,畢竟一個(gè)方便的工具可以大大提高效率,而這里學(xué)習(xí)Swift最快速地工具就是playground


1

playground 游樂場(chǎng)垫毙,可以立刻獲得編譯后的效果


快速入門

  • 創(chuàng)建對(duì)象
  • OC
      [[UIView alloc] initWithXXX:];
    
  • Swift
    UIView(xxx)
    
2
  • 調(diào)用方法
    • OC
        [UIColor redColor]
      
  • Swift
      UIColor.redColor
    
  • 枚舉
    • OC
        UIButtonTypeContactAdd
      
    • Swift
        UIButtonType.ContactAdd
      

輸出

  • OC NSLog(@"Hellow World");
  • Swift print("Hellow World");

常量變量

  • OC
    • 變量 int a = 20;
    • 常量 const int a = 20
  • Swift
    • 在Swift語言中霹疫,所有的類型的第一個(gè)字母均是大寫,Int,Double...
    • 變量 - var
  var a1:Int = 20
  • 常量 - let
let a1:Int = 20
3
  • 快捷鍵: 按住option,點(diǎn)擊综芥,可以查看他的信息


    4
  • 數(shù)據(jù)類型

    • OC中的數(shù)據(jù)類型首字母變成大寫丽蝎,就是Swift中的數(shù)據(jù)類型
  • 注意點(diǎn):

    • 在Swift開發(fā)中,一般情況下應(yīng)該先用let膀藐,只要在需要修改數(shù)據(jù)時(shí)才改用var,使用let的好處是屠阻,避免數(shù)據(jù)被修改,可以保證數(shù)據(jù)安全性
  • 類型推斷

    • Swift中如果在定義變量/常量時(shí)進(jìn)行初始化, 那么數(shù)據(jù)類型可以不用寫, 系統(tǒng)會(huì)自動(dòng)根據(jù)右邊的復(fù)制推導(dǎo)出變量/常量的類型
    • Swift開發(fā)中能不寫數(shù)據(jù)類型就不寫數(shù)據(jù)類型, 盡量使用編譯器的自動(dòng)推導(dǎo)
    • 只有當(dāng)我們需要明確的指定數(shù)據(jù)的長度, 獲取需要先定義再初始化時(shí)才明確的指定數(shù)據(jù)類型
    • 使用自動(dòng)類型推導(dǎo)好處: 大大降低代碼中的冗余代碼
    • 指定類型 let num:Int = 20
    • 自動(dòng)推導(dǎo) let num = 20
5
  • 類型轉(zhuǎn)換:
    • OC中有顯示轉(zhuǎn)換和隱式轉(zhuǎn)換 double value = 10.1 + 9
    • Swift中只有顯示轉(zhuǎn)換沒有隱式轉(zhuǎn)換, 也就是說只有相同類型的數(shù)據(jù)才能進(jìn)行賦值和計(jì)算

元組

  • 復(fù)合數(shù)據(jù)類型
  • 只要將多個(gè)相同或者不同的數(shù)據(jù)用()括起來就是元祖
  • 優(yōu)點(diǎn): 在以前沒有元祖之前C和OC語言是通過傳入指針或者返回結(jié)構(gòu)體的方式來返回多個(gè)值的, 而有了元祖之后就可以實(shí)現(xiàn)讓一個(gè)函數(shù)返回多個(gè)值
let number1:(Int,Double,CGFloat,NSInteger) = (1,1.1,1.11,2)
number1.0
number1.1
number1.2
number1.3
// 給元組的元素起名
/*
元祖的其它定義方式:指明應(yīng)用元祖元素的名稱
*/
let person = (name:"tym", age:18, score:100.0)
person.name
person.age
person.score
// 提取元組的數(shù)據(jù)
/*
元祖的其它定義方式:
通過指定的名稱提取元祖對(duì)應(yīng)的值, 會(huì)將對(duì)應(yīng)位置的值 賦值給對(duì)應(yīng)位置的名稱
*/
let (name, age, score) = ("tym", 18, 100.0)
name
age
score
/*
如果不關(guān)心元祖中的某個(gè)值可以利用_通配符來忽略提取
*/
let (name1 , age1 , _) =  ("tym", 18, 99.8)
print(name1)
print(age1)

分支

  • Bool 類型

    • C 和OC并沒真正的Bool類型额各,非0即真
      • OC語言的Bool類型YES/NO是typedef signed char BOOL;
    • Swift引入了真正的Bool類型
      • Swift中沒有C和OC中非零即真的概念
      • Swfit中邏輯值只有兩個(gè)true/false
  • if語句

    • Swift
      • 大部分用法和OC中一致
      • Swift中條件語句可以不用寫()
      • OC中如果if后面只有一條語句, 那么{}可以省略, 但是Swift不行
      • OC中條件語句可以是任何數(shù)值, OC中非0即真, YES/NO
      • Swift中條件語句的取值必須Bool類型, 也就是說Swift中提供了真正的Bool類型, true/false
let number = 10
//if number = 10 // Swift有效的避免了這種問題
if number == 10
{
    print(number)
}
  • 三目運(yùn)算符
    • 大部分用法和OC一樣
    • 條件表達(dá)式只能是Bool值
print(age >= 18 ? "開網(wǎng)卡":"回家")
  • switch語句
    • 大部分用法和OC一樣
    • Swift中條件語句可以不用寫()
    • OCdefault可以省略, 而Swift中大部分情況不能省略,而且default只能夠放在最后面的位置
    • OC中default的位置可以隨便寫, 而Swift不可以
    • OC中每個(gè)case后面必須加上break, 否則會(huì)出現(xiàn)穿透, 而Swift不會(huì)穿透, 也就是說不用寫break
    • OC中要在case中間定義變量必須加上{}, 否則作用域混亂, 而Swift不用
    • Swift可以判斷對(duì)象類型国觉,區(qū)間和元祖,OC只可以判斷整數(shù)
let score = 100
switch score
{
case 59:
    print("不及格")
case 100:
    print("滿分")
default:
    print("Other")
}

var rank = "A"
switch rank{
    case "A": //相當(dāng)于if
        print("優(yōu)")
    case "B": // 相當(dāng)于else if
        print("優(yōu)")
    case "C": // 相當(dāng)于else if
        print("優(yōu)")
    default: // 相當(dāng)于else
        print("沒有評(píng)級(jí)")
}

/*
因?yàn)椴荒艽┩杆圆荒苓@么寫
var rank1 = "A"
switch rank1{
    case "A":
    case "B":
        print("優(yōu)")
    case "C":
        print("優(yōu)")
    default:
        print("沒有評(píng)級(jí)")
}
*/

//只能這么寫
var rank1 = "A"
switch rank1{
    case "A", "B": // 注意OC不能這樣寫
        print("優(yōu)")
    case "C":
        print("差")
    default:
        print("沒有評(píng)級(jí)")
}
  • 區(qū)間
    • 閉區(qū)間: 0...10 , 取值范圍0~10,包含頭包含尾
    • 半閉區(qū)間: 0..<10 , 取值范圍0~9,包含頭不包含尾
switch score
{
case 0..<60:  // 0 ~ 59
    print("不及格")
case 60..<80:  // 60 ~ 79
    print("良好")
case 80..<100: // 80 ~ 99
    print("優(yōu)秀")
default:
    print("滿分")
}
// 判斷元組
let point = (100, 50)
switch point
{
case (0,0):
    print("原點(diǎn)")
case (50,50):
    print("中點(diǎn)")
case (100,100):
    print("右下角")
default:
    print("Other")
}

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

// 根據(jù)條件綁定
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")
}

可選類型

  • 可選類型
    • 一個(gè)變量可以有值可以沒有值, 我們就稱之為可選類型
    • 在Swift中如果使用一個(gè)可選類型的變量/常量, 必須解包操作
      • 解包: 只需要在變量/常量后面加上 !
      • !含義: 代表告訴系統(tǒng)該變量/常量中一定有值, 如果強(qiáng)制解包一個(gè)沒有值的常量/變量,那么會(huì)報(bào)錯(cuò)
    • 優(yōu)點(diǎn): 提高代碼閱讀性
    • 格式:
      • 修飾符 變量名稱:Optional<數(shù)據(jù)類型>
      • 修飾符 變量名稱: 數(shù)據(jù)類型?
    • 語法糖: 因?yàn)樵赟wift中可選類型用得非常非常多, 所以為了簡化代碼, Swift提供了一個(gè)語法糖, 可以用? 代替 Optional<數(shù)據(jù)類型>
Snip20151018_11.png

7
  • 注意:
    • 在開發(fā)中一般情況下盡量不要強(qiáng)制解包一個(gè)可選類型, 否則會(huì)引發(fā)錯(cuò)誤
    • 可選綁定: 為了更安全的解析可選類型的值, 一般情況下使用可選綁定
      • 如果沒有值就不會(huì)做任何操作, 如果有值會(huì)返回true并將optValue的值賦值給result執(zhí)行大括號(hào)中的內(nèi)容
/*
// 這樣不嚴(yán)謹(jǐn)
let url = NSURL(string: "http://www.hao123.com/")
print(url)
let request = NSURLRequest(URL: url!)
*/

let url = NSURL(string: "http://www.hao123.com")
print(url)
if url != nil
{
    let request = NSURLRequest(URL: url!)
}

// 可選綁定: 如果url不為nil, 系統(tǒng)內(nèi)部就會(huì)自動(dòng)將解包之后的值賦值給temp, 并且只有temp有值時(shí)才會(huì)執(zhí)行{}中的代碼
// Swift開發(fā)中推薦這種寫法
if let temp = url
{
    let request = NSURLRequest(URL: temp)
}

循環(huán)語句

  • for循環(huán)
    • 傳統(tǒng)的for
/*:
傳統(tǒng)for
* 基本用法和OC一致
* for后面的()可以省略
* for后面的{}不可用省略
* Swift開發(fā)中不建議使用傳統(tǒng)for循環(huán)
*/
for var i = 0; i < 10; i++
{
    print(i)
}
// 一直循環(huán)
//for ;;
//{
//    print("---")
//}
  • 推薦的for循環(huán)形式
// Swift開發(fā)者中推薦的for循環(huán)格式
for i in 0..<10
{
    print(i)
}
  • while 循環(huán)
    • 基本用法和OC一致
var number = 0
while number < 10
{
    print(number)
    number++
}
  • do-while 循環(huán)
    • 基本用法和OC一致
    • Swift2.0開始dowhile循環(huán)中沒有do, 只有repeat, 因?yàn)閐o被作用異常處理
var index = 0
repeat{
    print(index)
    index++
}while index < 10

數(shù)組

  • 格式 var arr: Array<Int> / var arr: [Int]
  • 可變和不可變 var/let
// 1.遍歷數(shù)組(取值)
arr[0]
for item in arr
{
    print(item)
}
// 2.添加
arr.append(3)

// 3.修改
arr[1] = 9

// 4.刪除
arr.removeAtIndex(0)

// 5.合并
var arr1 = [3, 5, 7]
arr += arr1

// 6.Swift特殊
for item in arr[0..<2] // 0~1
{
    print(item)
}

//arr.removeRange(Range(start: 0, end: 2))
//arr

// 通過觀察可以發(fā)現(xiàn)Range其實(shí)就是一個(gè)半閉區(qū)間
arr.removeRange(0..<2)
arr

arr += arr1[0..<2]

字典

  • 格式 var dict: Dictionary<String, String>
  • 注意: 將OC的{}換成了[]
  • 可變和不可變 var/let
var dictTest: Dictionary<String,String>
var dictTest2: [String: String]

var dict = ["name":"tym", "age":"18"]

// 企業(yè)開發(fā)中字典使用的最多的類型就是 [String: NSObject] 類型
var dict2 = ["name":"tym", "age":"18", "score":99.99]

// 取值
dict2["age"]

// 修改
dict2["age"] = 20
dict2

// 增加
dict2["rank"] = 10
dict2

// 刪除
dict2.removeValueForKey("name")
dict2
// removeValueForKey返回一個(gè)可選類型, 如果字典中不存在需要?jiǎng)h除的key, 那么返回nil并且不會(huì)執(zhí)行任何操作, 如果存在則刪除key對(duì)應(yīng)的值, 并且返回被刪除的值
var dict14 = ["name":"lnj", "age":30]
if let orignal = dict14.removeValueForKey("names")
{
    print(dict14)
    print(orignal)
}
print(dict14)

var dict15 = ["name":"lnj", "age":30]
dict15.removeAll(keepCapacity: true)

// 遍歷
var dict17 = ["name":"lnj", "age":30]
for key in dict17.keys
{
    print("key = \(key)")
}

var dict18 = ["name":"lnj", "age":30]
for value in dict18.values
{
    print("value = \(value)")
}
// Swift寫法
// 系統(tǒng)會(huì)自動(dòng)將字典中的key賦值給元祖中的第一個(gè)遍歷, 會(huì)自動(dòng)將字典中的value賦值給元祖中的第二個(gè)遍歷
for (key,object) in dict2
{
    print(key)
    print(object)
}

// 合并
var dict3 = ["name":"tym", "sex":"M", "height":179.9]
var dict4 = ["weight":120, "score":100.0]
for (key,value) in dict4
{
    dict3[key] = value
}
dict3

字符串

  • OC的字符串是NSString, Swift的字符串String
  • OC的字符串是一個(gè)對(duì)象, Swift字符串是一個(gè)結(jié)構(gòu)體, 效率更高
  • OC中的字符串是一個(gè)\0結(jié)尾, Swift字符串不是以\0結(jié)尾
  • Swift中的字符串支持遍歷
let str = "Hi, \0 Tym"

// 遍歷字符串
for c in str.characters
{
    print(c)
}

// 字符串拼接
var str2 = "Hello,World!"
str2 += str

// 字符串格式化
let name = "tym"
let age = 18
let res = "name: \(name) , age: \(age)"

// 2015-10-19 13:55
let str3 = String(format: "%d-%02d-%02d %02d:%02d", arguments: [2015,10,19,13,55])

// 截取字符串
// 提示: 在Swift開發(fā)中, 我們經(jīng)常需要將Swift的字符串轉(zhuǎn)換為OC的字符串來操作, 并且Swift自身也意識(shí)到了這一點(diǎn), 所以在OC字符串和Swift的字符串之間轉(zhuǎn)換相當(dāng)簡單
let str4 = "ttyymm"
let str5: NSString = str4
str5.substringToIndex(4)
str5.substringWithRange(NSMakeRange(0, 1))

// 計(jì)算字符串長度
var stringValue = "abc李"
print(stringValue.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
// 打印結(jié)果6, 和C語言一樣計(jì)算字節(jié)數(shù)

// as 就是把什么當(dāng)做什么
(str4 as NSString).substringFromIndex(2)

函數(shù)

  • 格式
func 函數(shù)名稱(形參列表) ->返回值類型
{
        代碼
}```
* Void == ()

```objc
// 1.沒有參數(shù)沒有返回值,沒有返回值時(shí)可不寫返回值
func say() -> Void
{
    print("Hi!")
}
func say1() -> ()
{
    print("Hi!")
}
say1()
func say2()
{
    print("Hi!")
}
say2()

// 2.有參數(shù)沒有返回值
// Swift2.0開始, 會(huì)自動(dòng)將形參列表的第二個(gè)參數(shù)名稱作為標(biāo)簽
// Swift2.0之前是沒有這個(gè)特性的, 在Swift2.0之前如果需要顯示標(biāo)簽需要在形參名稱前面加上#
func sum(num1:Int, num2:Int)
{
    print(num1 + num2)
}
sum(10, num2: 20)

// 3.沒有參數(shù)有返回值
func getNumber() -> Int
{
    return 998
}
getNumber()

// 4.有參數(shù)有返回值
func sum2(num1:Int, num2:Int) -> Int
{
    return num1 + num2
}
print(sum2(11, num2: 22))
  • 內(nèi)部和外部參數(shù)
    • 默認(rèn)情況下所有形參都是內(nèi)部參數(shù), 也就是說只能在函數(shù)內(nèi)部使用
    • 從Swift2.0開始會(huì)自動(dòng)將形參列表的第二個(gè)參數(shù)名稱作為標(biāo)簽, 也就是說從第二個(gè)參數(shù)開始, 參數(shù)的名稱既是內(nèi)部參數(shù)又是外部參數(shù)
    • 如何指定外部參數(shù)? 在方法中的參數(shù)的前面加上外部參數(shù)名
// 這里的yy就是外部參數(shù)
func sum3(num1:Int, yy num2:Int)
{
    print("num1: \(num1), num2: \(num2)")
}
//sum3(100, num2: 200)
sum3(100, yy: 300)
  • 默認(rèn)參數(shù)
    • 如果指定了默認(rèn)值, 那么在調(diào)用方法的時(shí)候就可以不用傳遞數(shù)據(jù), 如果不傳遞數(shù)據(jù)系統(tǒng)就會(huì)使用默認(rèn)值, 如果傳遞了就會(huì)使用傳遞的值
    • 在其它語言里面, 默認(rèn)值一般情況只能是最后一個(gè)參數(shù), 但是Swift可以寫在任何位置
    • 構(gòu)造方法中麻诀,不能設(shè)置默認(rèn)參數(shù)
func joinSting(str1: String, str2: String = "是", str3: String) -> String
{
    return str1 + str2 + str3
}
joinSting("tym", str2: "不是", str3: "帥哥")
joinSting("tym", str3: "帥哥")
  • 常量參數(shù)痕寓、變量參數(shù)以及inout參數(shù)
    • 默認(rèn)情況下所有形參都是常量參數(shù), 不能在函數(shù)中修改形參的值
    • 如果想在函數(shù)中修改形參的值, 那么必須把形參變?yōu)樽兞繀?shù)
    • 和OC一樣, 在函數(shù)中修改形參的值不會(huì)影響到外面實(shí)參的值
    • 如果想在函數(shù)中修改形參之后影響實(shí)參, 那么必須把形參變?yōu)閕nout參數(shù)
//func swap(a: Int, b: Int)
//{
//    let temp = a
//    a = b      // 不能修改常量
//    b = temp
//}
//func swap(var a: Int,var b: Int)
//{
//    let temp = a
//    a = b
//    b = temp
//    print("a = \(a), b = \(b)")
//}
//var a = 23
//var b = 24
//swap(&a, &b)
//
func swap1(inout a: Int,inout b: Int)
{
    let temp = a
    a = b
    b = temp
    print("a = \(a), b = \(b)")
}
var a1 = 23
var b1 = 24
print("a = \(a1), b = \(b1)")
swap1(&a1, b: &b1)
print("a = \(a1), b = \(b1)")
  • 可變參數(shù)
    • 只要參數(shù)是可變參數(shù), 就可以傳遞一個(gè)多個(gè)
    • 在其它語言中一般情況下可變參數(shù)只能是最后一個(gè)形參, 而Swift中可以寫在任意位置, 但是為了提高代碼的閱讀性, 還是建議寫在最后
func sum4(numbs:Int..., temp:Int , temp2: Int) -> Int
{
    var sum = 0
    for i in numbs
    {
        sum += i
    }
    return sum + temp + temp2
}
sum4(3, temp: 10, temp2: 20)
  • 函數(shù)嵌套
    • 將一個(gè)函數(shù)寫到另外一個(gè)函數(shù)的函數(shù)體中, 外面稱之為函數(shù)嵌套
      • 1.被嵌套的函數(shù)只能在父函數(shù)內(nèi)部訪問
      • 2.被嵌套的函數(shù)可以訪問外部的變量
    • 應(yīng)用場(chǎng)景: 兩個(gè)函數(shù)之間依賴較強(qiáng), 或者一個(gè)函數(shù)就只給另外一個(gè)函數(shù)使用
      • 例如: 對(duì)數(shù)組排序是一個(gè)函數(shù), 交換變量又是一個(gè)函數(shù), 他們就可以使用函數(shù)嵌套
let value = 23
func test(inout a:Int)
{
    let number = 10
    func demo()
    {
        print("\(number)", "\(a)", "\(value)")
    }
    demo()
}
var tes = 110
test(&tes)

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

  • 當(dāng)重寫一個(gè)類的構(gòu)造方法時(shí),這個(gè)類會(huì)暗自幫我們調(diào)用super.init()
  • 定義屬性蝇闭,直接寫在class里面
    • 必須給這個(gè)類中所有的屬性進(jìn)行初始化
    • 如果不能在創(chuàng)建對(duì)象時(shí)給這個(gè)類中所有的屬性進(jìn)行初始化呻率,那么這些屬性必須是可選的(?)
  • 注意:
    • 如果自定義一個(gè)類, 并且沒有重寫構(gòu)造方法, 那么系統(tǒng)會(huì)提供默認(rèn)的構(gòu)造方法
    • 如果自定義一個(gè)類, 并且自定義了構(gòu)造方法, 并且沒有重寫原始的構(gòu)造方法,那么系統(tǒng)不會(huì)提供默認(rèn)的構(gòu)造方法
      • 如果還需要原來的構(gòu)造方法呻引,需要重寫該構(gòu)造方法(盡管里面什么都不處理)
  • Swift中要求在創(chuàng)建一個(gè)類時(shí)必須給這個(gè)類中所有的屬性進(jìn)行初始化
    • 如果不能在創(chuàng)建對(duì)象時(shí)給這個(gè)類中所有的屬性進(jìn)行初始化, 那么這些屬性必須可選的
    • 如果已經(jīng)在構(gòu)造方法中對(duì)所有的屬性進(jìn)行了初始化, 那么這些屬性就可以不是可選類型
    • 在給某一個(gè)類指定屬性的數(shù)據(jù)類型時(shí), 如果該屬性是對(duì)象類型, 那么可以指定為可選類型
    • 如果該屬性不是對(duì)象類型而是基本數(shù)據(jù)類型, 那么建議直接賦值為0
      • 如果屬性是基本數(shù)據(jù)類型, 并且是可選類型, 系統(tǒng)不會(huì)自動(dòng)分配存儲(chǔ)空間,在KVC的時(shí)候會(huì)出現(xiàn)問題
var name: String?
var age: Int = 0
    
    // 重寫構(gòu)造方法
    override init() {
        // 注意: 在構(gòu)造方法中必須先初始化本類再初始化父類
        name = "tym"
        age = 18
        // 當(dāng)我們重寫一個(gè)類的構(gòu)造方法時(shí), 系統(tǒng)內(nèi)部會(huì)悄悄得幫我們調(diào)用super.init()
        super.init()
    }
    
    // 自定義構(gòu)造方法
    init(name: String, age: Int) {
        self.name = name
        self.age = age
        // 以下這句代碼礼仗,能不寫就不寫
//        super.init()
    }
    
    init(dict: [String: NSObject]) {
        // 注意:Swift中如果想在構(gòu)造方法中使用KVC轉(zhuǎn)換模型, 必須先調(diào)用 super.init()
        // 調(diào)用 super.init()的目的主要是為了給對(duì)象分配存儲(chǔ)空間
        super.init()
        setValuesForKeysWithDictionary(dict)
    }
    // Swift中打印對(duì)象,會(huì)調(diào)用以下屬性,重寫此屬性逻悠,方便測(cè)試
    override var description: String {
//        return "name:\(name), age:\(age)"
        let keys = ["name","age"]
        let dict = dictionaryWithValuesForKeys(keys)
        return "\(dict)"
    }

setter元践、getter方法

  • OC
    • setXXX
    • getXXX
  • Swift
    • willSet、didSet
    • get
      • 如果只是想重寫一個(gè)屬性的get方法蹂风,可以直接return
var name: String?
        {
            // 在Swift開發(fā)中用以下兩個(gè)方法代替OC中的重寫setter方法
            willSet{
                print("賦值之前的調(diào)用\(newValue)")
            }
            didSet{
                print("賦值之后的調(diào)用\(oldValue)")
            }
    }
    
    var age: Int
        {
            // 在Swift中如果只重寫了get方法, 那么該屬性就是一個(gè)只讀屬性readOnly
            // 如果一個(gè)屬性只重寫了get方法, 我們也稱之為"計(jì)算型屬性", 計(jì)算型屬性是不具備存儲(chǔ)能力的
//            get{
//                return 110
//            }
            
            // 如果只是想重寫一個(gè)屬性的get方法, 那么可以簡寫
            return 120
    }

閉包

  • OC
    • block類似于匿名函數(shù)卢厂,用于封裝代碼塊,在特定的時(shí)候執(zhí)行一些耗時(shí)操作
    • 類型格式:返回類型 (^block名字)(參數(shù)列表)
    • 值格式: ^(形參列表){
      需要執(zhí)行的代碼
      }

<returnType>(^<blockName>)(<parameterTypes>) = ^(<parameters>) {
<statements>
};


```objc
@implementation ViewController

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self loadData:^{
        NSLog(@"刷新UI");
    }];
}

-(void)loadData:(void (^)())finishBlock {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"加載數(shù)據(jù)");
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"%@",[NSThread currentThread]);
            finishBlock();
        });
    });
}

@end
  • Swift
    • 閉包是用于定義函數(shù)(Swift中函數(shù)就是閉包惠啄,閉包是一個(gè)特殊的函數(shù))慎恒,執(zhí)行一些耗時(shí)操作
    • 類型格式:(形參列表)->返回值類型
    • 值格式:
      {
      (形參列表)->返回類型
      in
      需要執(zhí)行的代碼
      }
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadData ({ () -> () in
            print("刷新UI")
        })
    }
    
    func loadData(finish:()->()) {
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print(NSThread.currentThread())
            print("更新數(shù)據(jù)")
            
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                print(NSThread.currentThread())
                finish()
            })
        }
    }
}
  • 閉包的寫法
    • 完整寫法

loadData ({ () -> () in
print("更新UI")
})

+ 如果閉包`沒有形參`, 那么in和in之前的代碼都可以省略
```objc
loadData ({ 
          print("更新UI")
      })
  • 如果閉包是函數(shù)的最后一個(gè)參數(shù), 那么閉包可以寫在函數(shù)()的后面
loadData ( ){ () -> () in
          print("更新UI")
      }
  • 如果函數(shù)只有一個(gè)閉包參數(shù), 那么函數(shù)的()可以省略
loadData {
          print("更新UI")
      }
  • 閉包的循環(huán)引用問題
    • OC
      • __weak : 如果對(duì)象釋放, 會(huì)自動(dòng)設(shè)置為nil
      • __unsafe_unretained: 如果對(duì)象釋放, 不會(huì)自動(dòng)設(shè)置為nil
    __weak typeof(self) weakSelf = self
    
    • Swift
      • 對(duì)應(yīng)關(guān)系: _weak == weak , _unsafe_unretained == unowned
      weak var weakSelf = self
      loadData { () -> () in
              print("刷新UI")
              weakSelf!.view.backgroundColor = UIColor.greenColor()
          }
      
      // 不建議此方法,因?yàn)閺?qiáng)制解包了
      loadData { [weak self] () -> () in
              print("刷新UI")
              self!.view.backgroundColor = UIColor.greenColor()
          }
      

// 因?yàn)閡nowned相當(dāng)于_unsafe_unretained撵渡,不會(huì)設(shè)置成nil,所有不用強(qiáng)制解包
loadData { [unowned self] () -> () in
print("刷新UI")
self.view.backgroundColor = UIColor.greenColor()
}
```

  • 單例

    • OC
     @interface Dog : NSObject
        + (instancetype)sharedDog;
     @end
      @implemetion Dog
        +(instancetype)sharedDog {
            static Dog *_instance = nil;
            // onceToken默認(rèn)等于0, 只要執(zhí)行一次之后就不等于0了, 原理是通過判斷onceToken是否等于0決定是否需要執(zhí)行block
            static dispatch_once_t onceToken;
            NSLog(@"%ld",onceToken);
            dispatch_once(&onceToken, ^{
                _instance = [[self alloc] init];
            });
            return _instance;
      }
    
    • Swift
      • 注意:在func前添加class標(biāo)記融柬,相當(dāng)于是類方法,不添加趋距,相當(dāng)于是對(duì)象方法
      // 方法一
      static var onceToken:dispatch_once_t = 0;
      static var _instance:Dog?
      class func sharedDog() -> Dog {
          print(onceToken)
          dispatch_once(&Dog.onceToken) {
              _instance = Dog()
          }
          return _instance!
      }
    
      // 方法二
      // 因?yàn)槭浅A苛Q酰灾荒苜x值一次
      static let _instance:Dog = Dog()
      class func sharedDog()->Dog {
          return _instance
      } 
    
      // 方法三,強(qiáng)烈推薦的方法
      // 而且蘋果有統(tǒng)一的命名規(guī)范, 但凡是單例統(tǒng)一是shareInstance
      static let shareInstance:Dog = Dog()
    

懶加載

  • 延遲存儲(chǔ)屬性
    • Swift語言中所有存儲(chǔ)屬性必須有初始值, 也就是當(dāng)構(gòu)造完一個(gè)對(duì)象后, 對(duì)象中所有的存儲(chǔ)屬性必須有初始值, 但是也有例外, 其中延遲存儲(chǔ)屬性可以將屬性的初始化推遲到該屬性第一次被調(diào)用的時(shí)候
  • 懶加載應(yīng)用場(chǎng)景:
    • 1.有可能不會(huì)用到
    • 2.依賴于其它值
  • 格式:
    • lazy var 變量: 類型 = { 創(chuàng)建變量代碼 }()
    • 懶加載的寫法本質(zhì)上是定義并執(zhí)行一個(gè)閉包
    lazy var demoView: UIView = { 
        let v = UIView(frame: CGRectMake(10, 10, 100, 100)) 
        v.backgroundColor = UIColor.redColor() return v
    }()

gurad

  • ?蘋果公司意識(shí)到Swift編寫的代碼节腐,會(huì)不知不覺得多層嵌套外盯,然后代碼變得非常丑陋,所以在Swift2.0的時(shí)候翼雀,專門推出了一個(gè)條件語句guard
  • gurad 專門守護(hù)安全的
  • 格式:
guard 條件語句 else {
需要執(zhí)行的語句
return
}```
- 特點(diǎn):只有條件為假的時(shí)候饱苟,才會(huì)執(zhí)行else中的代碼,相對(duì)于if else,這個(gè)只有else
- 作用: 用于過濾數(shù)據(jù)

---

# private
- 在Swift中狼渊,添加一個(gè)屬性或者方法可以在其他項(xiàng)目中的文件訪問
- 為了封裝性箱熬,可以添加private在屬性或者方法或者類前,可以讓該屬性或者方法只能在`當(dāng)前`文件中訪問
- 注意:
  + 由于點(diǎn)擊事件是由NSRunLoop發(fā)起的狈邑,并不是當(dāng)前的類發(fā)起的城须,如果在點(diǎn)擊方法前添加private,那么NSRunLoop無法找到該方法米苹,會(huì)導(dǎo)致崩潰
  + OC是基于運(yùn)行時(shí)動(dòng)態(tài)派發(fā)事件的
  + Swift是編譯時(shí)就已經(jīng)確定了方法

---

# @objc
- 想給監(jiān)聽點(diǎn)擊事件的方法加上private糕伐,并且又想讓系統(tǒng)動(dòng)態(tài)派發(fā)時(shí)找到該方法,可以在該方法前加上@objc驱入,@objc就能讓這個(gè)方法支持動(dòng)態(tài)派發(fā)

```objc
@objc private func composeBtnClick()
{
}

便利構(gòu)造方法

  • 在Swift開發(fā)中赤炒,如果想要快速創(chuàng)建一個(gè)對(duì)象氯析,那么可以提供一個(gè)便利構(gòu)造器(遍歷構(gòu)造方法)
  • 在普通構(gòu)造方法前面加上一個(gè)convenience,那么這個(gè)構(gòu)造方法就是一個(gè)便利構(gòu)造方法
  • 注意:
    • 如果定義一個(gè)便利構(gòu)造器,那么必須在便利構(gòu)造方法中調(diào)用指定構(gòu)造方法(沒有convenience單詞的構(gòu)造方法)
// 以下方式的確可以快速創(chuàng)建一個(gè)對(duì)象莺褒,但是Swift不是這種風(fēng)格
    
    class func createBtn(image:String, backgroundImage:String)->UIButton
    {
        let btn = UIButton(type: UIButtonType.Custom)
        btn.setImage(UIImage(named: image), forState: UIControlState.Normal)
        btn.setImage(UIImage(named: image + "_highlighted"), forState: UIControlState.Highlighted)
        btn.setBackgroundImage(UIImage(named: backgroundImage), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: backgroundImage + "_highlighted"), forState: UIControlState.Highlighted)
        
        btn.sizeToFit()
        
        return btn
    }


/*
    定義便利構(gòu)造器步驟:
    1.編寫一個(gè)構(gòu)造方法
    2.在構(gòu)造方法前面加上 convenience
    3.在構(gòu)造方法中調(diào)用當(dāng)前類的其他"非便利構(gòu)造器"初始化對(duì)象
    */
    convenience init(imageName: String, backImageName: String)
    {
        self.init()
        
        // 1.設(shè)置背景圖片
        setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
        setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)
        
        // 2.設(shè)置普通圖片
        setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
        setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)
        
        sizeToFit()
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掩缓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子遵岩,更是在濱河造成了極大的恐慌你辣,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尘执,死亡現(xiàn)場(chǎng)離奇詭異舍哄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)誊锭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門表悬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丧靡,你說我怎么就攤上這事蟆沫。” “怎么了温治?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵饭庞,是天一觀的道長。 經(jīng)常有香客問我熬荆,道長舟山,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任卤恳,我火速辦了婚禮累盗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘突琳。我一直安慰自己幅骄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布本今。 她就那樣靜靜地躺著,像睡著了一般主巍。 火紅的嫁衣襯著肌膚如雪冠息。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天孕索,我揣著相機(jī)與錄音逛艰,去河邊找鬼。 笑死搞旭,一個(gè)胖子當(dāng)著我的面吹牛散怖,可吹牛的內(nèi)容都是我干的菇绵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼镇眷,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咬最!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起欠动,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤永乌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后具伍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翅雏,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年人芽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了望几。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萤厅,死狀恐怖橄抹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祈坠,我是刑警寧澤害碾,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站赦拘,受9級(jí)特大地震影響慌随,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜躺同,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一阁猜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹋艺,春花似錦剃袍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涛救,卻和暖如春畏邢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背检吆。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工舒萎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹭沛。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓臂寝,卻偏偏與公主長得像章鲤,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咆贬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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