Swift快速上手筆記

可選項(xiàng)

Optional可以讓我們擺脫很多不必要的判斷和取值谈截,聲明變量在類型后面加上?的語(yǔ)法

class Toy {
    let name: String
    init(name: String) {
        self.name = name
    }
}

class Pet {
    var toy: Toy?
}

class Child {
    var pet: Pet?
}

if let toyName = xiaoming.pet?.toy?.name {
    // 通過多級(jí)守護(hù)安全取到值
}

還有很多高級(jí)用法簸喂,后面慢慢研究。

if let & guard let

用于守護(hù)操作

// MARK: - if let / gucard let 用法
func ifletDemo() {
    let i:Int? = 10
    
    if let a = i {
        // 此處a 解包了i,如果a解包是nil則不成立
        print(a)
    } else {
        print("i is nil")
    }
    
    // 此處使用guard 減少邏輯分支層級(jí),a在后續(xù)使用已經(jīng)被解包
    guard let a = i else {
        print("i is nil")
        return
    }
    
    print(a)

}

switch

swift 的switch比OC要靈活很多唉锌,支持多種數(shù)據(jù)類型袄简,Int泛啸、String候址、浮點(diǎn)岗仑,結(jié)構(gòu)體荠雕, 并且支持使用元組值綁定稳其,結(jié)構(gòu)體值綁定驶赏。

let n = 10

switch n {
case 1:
    print("\(n)")
case 10:
    print("\(n)")
default:
    print("default")
}


// 多種類型, 字符串、Bool既鞠、結(jié)構(gòu)體煤傍、浮點(diǎn)
var str = "my"
switch str {
case "my":
    print("case my")
    fallthrough
case "d":
    print("1") //被輸出
default:
    print("default")
}

// 運(yùn)算區(qū)間
switch n {
case 0 ..< 5 :
    print("0~5")
case 5 ... 10 :
    print("5~10")
default:
    print("default")
}

// Value Binding  值綁定,適合和enum合用
let request = (6,"success")
switch request {
case (let errorCode, let state):
    print("\(state),\(errorCode)")
case (let errorCode, _):
    "error code is \(errorCode)"
}

// enum 結(jié)構(gòu)值綁定
enum Result {
    case Success(json: String, isSuccess: Bool)
    case Fail(error: String)
}

let r = Result.Success(json: "{}", isSuccess: true)

switch r {
case Result.Success(let json, let isSuccess):
    print("\(json)")
default:
    print("default")
}

for

swift 3.0 已經(jīng)去掉了 C 語(yǔ)言風(fēng)格的for循環(huán)嘱蛋。

let array = [1, 12, 9, 4]

// 遍歷數(shù)組
for i  in array {
    print(i)
}

// 條件區(qū)間
for i in 0...10 {
    print(i)
}

字符串

swift 中的字符串操作蚯姆,如果遇到不方便操作的時(shí)候記得轉(zhuǎn)為NSString

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

// 反序
for c in str.characters.reversed() {
    print(c)
}

// 轉(zhuǎn)換成NSString
let ocStr = str as NSString

// 字符串長(zhǎng)度
print(ocStr.length)
// 字節(jié)長(zhǎng)度
print(str.lengthOfBytes(using: .utf8))

// 截取字符串
let substr = ocStr.substring(with: NSMakeRange(0, 5))
print(substr)

數(shù)組

// MARK: -遍歷數(shù)組
func arrayDemo() {
    let myArray = [1, 2, 3]
    
    // 遍歷
    
    // 元組1
    print("-----遍歷數(shù)組1....")
    for e in myArray.enumerated() {
        print("\(e.offset), \(e.element)")
    }
    
    // 元組2
    print("-----遍歷數(shù)組2....")
    for (of, el) in myArray.enumerated() {
        print("\(of),\(el)")
    }
    
    // 直接遍歷
    print("-----遍歷數(shù)組3....")
    for item in myArray {
        print(item)
    }

    
    // 反轉(zhuǎn)數(shù)組
    print("-----反轉(zhuǎn)數(shù)組....")
    for item in myArray.reversed() {
        print(item)
    }
    
    print("-----")
    for (of, el) in myArray.enumerated().reversed() {
        print("\(of),\(el)")
    }
}

// MARK: - 數(shù)組拼接
func arrayAppendDemo() {
    
    print("------數(shù)組拼接")
    var array = ["1", "test"]
    print(array)
    
    // 數(shù)組添加元素
    array.append("x")
    let array1 = ["a", "b", "c"]
    
    array += array1
    
    print(array)
    
    
    print("------")
    // 數(shù)組的拼接需要在同類型下進(jìn)行
    var array2: [Any] = [2, "tt"] as [Any]
    let array3: [Any] = ["a", "b", "c"]
    array2 += array3
    
    print(array2)
}

字典

// 字典遍歷
func demo() {

    // Swift3.1 必須要轉(zhuǎn)為一個(gè)確定的類型 as [String:Any]
    let dic = ["name":"alienjunx", "age":20] as [String:Any]
    print(dic)

    // 直接遍歷
    for (k,v) in dic {
        print("\(k),\(v)")
    }
    
    print("-----")
    for item in dic {
        print("\(item.key),\(item.value)")
    }
}

// 合并
func demo2() {
    print("-----合并")
    var dic1 = ["name":"alienjunx", "age":20] as [String:Any]
    print(dic1)
    
    let dic2 = ["height":90, "name":"老萬"] as [String:Any]
    print(dic2)
    
    for (k,v) in dic2 {
        dic1[k] = dic2[k]
    }
    
    print(dic1)

}

// 刪除
func removeDemo() {
    print("-----刪除")
    var dic1 = ["name":"alienjunx", "age":20] as [String:Any]
    print(dic1)
    
    dic1.removeValue(forKey: "name")
    print(dic1)
}

函數(shù)

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

// 函數(shù)返回一個(gè)String 類型
func myFunc() -> String {
    let i = "myFunc"
    return i
}

// 函數(shù)返回一個(gè)閉包
func loadMyName(name: String) -> ((String)->()) {
    print("\(name)")
    
    let result: ((String)->()) = {(rname: String)->() in
        
        print("\(rname),\(name)")
    }
    
    return result
}

loadMyName(name: "test")("my")

// 異步處理回調(diào)函數(shù)
// 參數(shù)的閉包需要進(jìn)行聲明 @escaping 逃逸閉包
func funcCallBack(completion: @escaping (_ json: String)->()) {
    DispatchQueue.global().async { 
        //// 耗時(shí)處理
        sleep(2)
        
        // 主線程回調(diào)
        DispatchQueue.main.async(execute: { 
            completion("ok")
        })
    }
}

funcCallBack { (resultStr) in
    print(resultStr)
}

閉包

與OC中的block一樣洒敏,都是一段提前準(zhǔn)備好的代碼龄恋,通常用于參數(shù)傳遞進(jìn)行處理回調(diào)結(jié)果

        // closure 是 '() -> ()' 一個(gè)閉包的類型
        // '=' 后面是實(shí)現(xiàn)這閉包  '閉包聲明 in  實(shí)現(xiàn)'
        let closure: () -> () = {() -> () in
            print("closure")
        }
        
        /*
         1.如果閉包是無參數(shù)無返回,則實(shí)現(xiàn)時(shí)可以省略  in和前面的聲明
         2.按照swift的類型推導(dǎo)凶伙,closure1的所屬類型也可以不顯示聲明
         */
        let closure1 = {
            print("closure1")
        }
        
        
        // 調(diào)用閉包
        closure()

        // 有參數(shù)的閉包
        let closure2 = { (name: String) -> () in
            print(name)
        }
        
        closure2("alienjunx")
        
        
        //---------------------------
        // 函數(shù)中傳遞閉包作為回調(diào)
        closureFunc(callBack: { (name) -> () in
            print(name)
        })

        // 如果函數(shù)的最后一個(gè)參數(shù)是閉包篙挽,可以使用尾隨閉包的方式簡(jiǎn)寫
        closureFunc { (name) in
            print(name)
        }

        // callBack 是一個(gè) (String) -> () 類型的閉包
        func closureFunc(callBack:(String) -> ()) {
            let myName = "testName"
            callBack(myName)
        }

??、?镊靴、铣卡!

let i:Int? = 10
// ?? 操作符,用于解包偏竟,如果Option中是nil煮落,則返回 后面的值
let num = i ?? 0

問號(hào)?
-- 聲明時(shí)添加踊谋?蝉仇,告訴編譯器這個(gè)是Optional的,如果聲明時(shí)沒有手動(dòng)初始化殖蚕,就自動(dòng)初始化為nil
-- 在對(duì)變量值操作前添加轿衔?,判斷如果變量時(shí)nil睦疫,則不響應(yīng)后面的方法害驹。
嘆號(hào)!
-- 聲明時(shí)添加蛤育!宛官,告訴編譯器這個(gè)是Optional的,并且之后對(duì)該變量操作的時(shí)候瓦糕,都隱式的在操作前添加底洗!
-- 在對(duì)變量操作前添加!咕娄,表示默認(rèn)為非nil亥揖,直接解包進(jìn)行處理

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

構(gòu)造函數(shù)在swift中都是以init命名

    override init() {
        name = ""
        
        // 會(huì)隱式調(diào)用super.init()
    }
    
    init(name: String) {
        self.name = name

        // 會(huì)隱式調(diào)用super.init()
    }
重寫

只要父類提供了可重寫的函數(shù),那么在子類中可以重新實(shí)現(xiàn)此函數(shù)圣勒,在swift中
-- 子類先初始化后父類才初始化费变,這與oc完全是不一樣的

class Person: NSObject {
    var name: String

    init(name: String) {
        self.name = name

        // 可不寫super.init() 會(huì)隱式調(diào)用
    }
}

// 繼承于Person
class Student: Person {
    var no: Int = 0

    // 重寫父類構(gòu)造函數(shù)
    override init(name: String) {
        super.init(name: name)
        self.no = 10
    }
}


let s = Student(name: "小明")
print("\(s.name) \(s.no)")

重載

函數(shù)名相同摧扇,參數(shù)類型和個(gè)數(shù)不同,重載不同的參數(shù)來滿足不同的初始化操作胡控,在OC中構(gòu)造函數(shù)重載用的非常多。

class Person: NSObject {
    var name: String
    var title: String?

    // 構(gòu)造方法1
    init(name: String) {
        self.name = name
    }
    
    // 構(gòu)造方法2
    init(name: String, title: String?) {
        self.name = name
        self.title = title
    }
}
便捷構(gòu)造函數(shù)

作為構(gòu)造函數(shù)的一種補(bǔ)充方式旁趟。 本身不負(fù)責(zé)對(duì)象的創(chuàng)建和初始化工作昼激,只是負(fù)責(zé)一些值的設(shè)置,并且可以通過條件判斷锡搜,進(jìn)行是否需要初始化橙困,防止不必要的內(nèi)存開銷,只要不滿足條件可以直接返回nil耕餐。
-- 必須調(diào)用的是自己的init凡傅,而不是父類的init
-- 不能被重寫
-- 可以用于extension 來擴(kuò)展控件的初始化操作

    // 便捷構(gòu)造函數(shù) (如果有初始化失敗的情況,記得init? 可選的情況)
    convenience init?(name: String, age: Int) {
        // 年齡小于0不滿足初始化條件
        // 直接返回nil肠缔,表示初始化失敗
        if age < 0  {
            return nil
        }
        
        // 對(duì)象真正初始化
        self.init()
        
        // 賦新的值
        self.name = name
    }
析構(gòu)函數(shù)

類似OC中的dealloc函數(shù)夏跷,可以在對(duì)象銷毀前做一些事情。
-- 不可直接調(diào)用
-- 不可重載
-- 對(duì)象銷毀前自動(dòng)調(diào)用

    deinit {
        // 跟蹤對(duì)象的銷毀
        // 必須釋放的資源
        
        /*
         -- 通知釋放明未,不釋放會(huì)造成內(nèi)存泄露
         -- kvo釋放槽华,崩潰
         -- NSTimer
         -- CADisplay
         */
    }

KVC

-- 不能對(duì)private修飾的屬性進(jìn)行賦值。
-- oc中是全部裸露趟妥,與swift不同

KVO

kvo 是基于kvc的猫态,都是OC運(yùn)行時(shí)的概念,在swift中還需要做額外的工作披摄,那就是將想要觀測(cè)的對(duì)象標(biāo)記為 dynamic亲雪。

import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

class MyClass: NSObject {
    dynamic var date = Date()
}

class MyClass1: NSObject {
    var date = Date()
}

class MyChildClass: MyClass1 {
    dynamic override var date: Date {
        get { return super.date }
        set { super.date = newValue }
    }
}

private var myContext = 0

class Class: NSObject {
    
    var myObject: MyClass!
    
    override init() {
        super.init()
        myObject = MyClass()
        print("初始化 MyClass,當(dāng)前日期: \(myObject.date)")
        myObject.addObserver(self,
            forKeyPath: "date",
            options: .new,
            context: &myContext)

        delay(3) {
            self.myObject.date = Date()
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?,
                            of object: Any?,
                               change: [NSKeyValueChangeKey : Any]?,
                              context: UnsafeMutableRawPointer?)
    {
        if let change = change, context == &myContext {
            let newDate = change[.newKey]
            print("日期發(fā)生變化 \(newDate)")
        }
    }
}

let obj = Class()

private & fileprivate & @objc

-- private 在swift3開始疚膊,private 就是真正的私有义辕,只能在本類中訪問(在extension或其他類中都不能訪問)。
-- fileprivate 在當(dāng)前文件中私有寓盗,別的文件不能訪問此關(guān)鍵字修飾的屬性和函數(shù)终息。
-- @objc 允許這個(gè)函數(shù)在運(yùn)行時(shí)通過OC的消息機(jī)制被調(diào)用
-- open > public > interal > fileprivate > private

extension

-- 不能有屬性
-- 不能重寫父類方法

extension String {
    func myFrist() -> String? {
        let str = (self as NSString)
        if str.length == 0 {
            return nil
        }
        let f = str.substring(with: NSMakeRange(0, 1))
        return f
    }
}

錯(cuò)誤處理

try?(有異常會(huì)返回nil) / try! (如果有異常就崩潰 )

let json = try? JSONSerialization.jsonObject(with: data! as Data, options: [])

捕獲錯(cuò)誤

do {
    let json =  try JSONSerialization.jsonObject(with: data! as Data, options: [])
} catch {
    print(error)
}

應(yīng)用實(shí)戰(zhàn)

一、runtime 獲取屬性
    class func propertyList() -> [String] {
        var count: UInt32 = 0
        var ptyList: [String] = []
        
        // 獲取屬性列表
        let list = class_copyPropertyList(self, &count)
        // 循環(huán)取出屬性
        for i in 0..<Int(count) {
            
            // 用guard let 來優(yōu)化  (贞让?周崭!)帶來的解包問題
            // UnsafePointer<Int8>? -> Byte(8個(gè)字節(jié))- Char ,C語(yǔ)言的字符串
            // 轉(zhuǎn)換成String
            guard let pty = list?[i],
                let cName = property_getName(pty),
                let name = String(utf8String: cName) else {
                    continue
            }
            ptyList.append(name)
        }
        
        // 釋放 C 語(yǔ)言對(duì)象
        free(list)
        print("屬性數(shù)量\(count)")
        
        return ptyList
    }
二喳张、循環(huán)引用

// 模擬加載數(shù)據(jù)的函數(shù)
func loadData(completion: @escaping () -> ()) {
    completion()
}

// weakSelf -> ViewController?
// OC的解決循環(huán)引用方法
weak var weakSelf = self
loadData {
    print(weakSelf?.view)
}

// Swift 推薦方法
// [weak self]  表示 {} 中所有self都是弱引用续镇,需要注意解包
loadData { [weak self] in
    print(self?.view)
}
三、懶加載
    // 懶加載
    // 懶加載的代碼只會(huì)在第一次調(diào)用的時(shí)候執(zhí)行閉包
    // 如果label被置為nil销部,懶加載也不會(huì)再次執(zhí)行
    /*
     1.延遲創(chuàng)建
     2.避免解包 摸航? 的煩惱
     */
    lazy var label: MyLabel = MyLabel()
    
    // 懶加載其實(shí)也是一個(gè)閉包
    // 上面的懶加載方式展開如下
    lazy var label = { () -> (MyLabel) in
        let l = MyLabel()
        return l
    }()
統(tǒng)計(jì)代碼行數(shù)

在項(xiàng)目根目錄下 以下命令

find . -name "*.swift" | xargs wc -l
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末制跟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酱虎,更是在濱河造成了極大的恐慌雨膨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件读串,死亡現(xiàn)場(chǎng)離奇詭異聊记,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恢暖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門排监,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人杰捂,你說我怎么就攤上這事舆床。” “怎么了嫁佳?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵挨队,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蒿往,道長(zhǎng)瞒瘸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任熄浓,我火速辦了婚禮情臭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赌蔑。我一直安慰自己俯在,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布娃惯。 她就那樣靜靜地躺著跷乐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趾浅。 梳的紋絲不亂的頭發(fā)上愕提,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音皿哨,去河邊找鬼浅侨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛证膨,可吹牛的內(nèi)容都是我干的如输。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼不见!你這毒婦竟也來了澳化?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤稳吮,失蹤者是張志新(化名)和其女友劉穎缎谷,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灶似,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡列林,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喻奥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片席纽。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捏悬,死狀恐怖撞蚕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情过牙,我是刑警寧澤甥厦,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站寇钉,受9級(jí)特大地震影響刀疙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扫倡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一谦秧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撵溃,春花似錦疚鲤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至语淘,卻和暖如春诲宇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惶翻。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工姑蓝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吕粗。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓它掂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子虐秋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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