Swift語(yǔ)法復(fù)習(xí)

// 教程地址:https://www.bilibili.com/video/BV1mT4y1C7JZ?p=16&vd_source=84310ee3c28453390868c23631486732

import UIKit
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // 數(shù)據(jù)類型轉(zhuǎn)換
//            let i: Int = 10
//            let j = 0.1
//            let c = Int(j) + i
//            print("c:\(c)")
//            
//            // 元組
//            let error = (tit: 400, ddd: "not found")
//            let d = error.0
//            print("d:\(d)")
//            
//            let (code, des) = error
//            print(code, des)
//            
//            let _ = error.tit
        }
        
        do {
            // if語(yǔ)句
//            var i = 10
//            if i > 0 {
//                print("i 大于 0")
//            }
        }

        // 循環(huán) 還可以使用where條件
        do {
//            var i = 10
//            repeat {
//                print(10)
//            } while i < 10
//            
//            for i in 0...3 {
//                print(i)
//            }
//            
//            for i in 0..<3 where i > 1 {
//                print(i)
//            }
//            
//            let array = [1, 2, 3 ,4]
//            for item in array[0..<2] {
//                print("haha\(item)")
//            }
//            
//            for item in array[...2] {
//                print(item)
//            }
        }
        
        // switch
        do {
            var c = "c"
            
            switch c {
            case "1":
                print("haha")
            case "2", "3":
                print("aaaa")
            default:
                break
            }
            
            // 區(qū)間匹配
            var index = 10
            switch index {
            case 0...1:
                fallthrough
                
            case 2...3:
                break
                
            default:
                break
            }
            
            // 元組匹配
            let tuple = (1, 1)
            switch tuple {
            case (_, 1):
                break
                
            case (1...2, 1):
                break
                
            case (1...2, 1..<3):
                break
                
            default:
                break
            }
            
            // 值綁定
            switch tuple {
            case (2, let a):
                print(a)
                
            case let (x, y):
                print(x, y)
                
            case let (a, b) where a > b: // 使用where過(guò)濾條件
                print(a)
            }
        }
    }

}

/// ------------
// 函數(shù)
func 函數(shù)() {
         
    // 有入?yún)?有返回值
    func func1(a: Int, b: Int) -> Int {
        return a + b
    }
    // 無(wú)入?yún)o(wú)返回值
    func fun2() {
        
    }
    // 帶參數(shù)標(biāo)簽和默認(rèn)參數(shù)值
    func fun3(outname inname: Int = 10) {
        
    }
    
    // 可變參數(shù)
    func fun4(numbers: Int..., age: Int) {
        for index in numbers {
            print(index)
        }
    }
    
    // 輸入輸出參數(shù)
    func fun5(a: inout Int) {
        a += 5
    }
    
    
}

/// ------------
 
func 別名typealias() {
    
    // 給元組聲明一個(gè)別名
    typealias Date = (year: Int, month: Int, day: Int)
    
    func eatAt(date: Date) {
        print(date.0)
        print(date.year)
    }
    eatAt(date: (2011, 2, 1))
    
    // 給函數(shù)聲明一個(gè)別名
    typealias DeleteFunc = (Int, Int) -> Int
    
    func operate(f: DeleteFunc, a: Int, b: Int) -> Int {
        return f(a, b)
    }
    
    
}
/// ------------
func 枚舉enum() {
    
    // 原始值 rawValue
    enum Score: Int {
        case point = 2 // 設(shè)置原始值
        case grade = 43 // 設(shè)置原始值
    }
    
    let s = Score.grade
    // 打印原始值
    print(s.rawValue)
    
    let _ = Score(rawValue: 65)
    
    // 隱式原始值,如果枚舉的原始值類型是Int或者String, swift會(huì)默認(rèn)設(shè)置原始值
    enum Di: String {
        case source // swift會(huì)默認(rèn)設(shè)置 case source  = "source"
        case north
    }
    
    
    typealias Location = (x: Int, y: Int)
    
    // 關(guān)聯(lián)值
    enum Direction {
        case sourth(Location)
        case east(Int)
        case west(Float)
    }
    
    var dir = Direction.sourth((10, 20))
    // 可以根據(jù)類型推斷出枚舉類型  就可以用.省略類型
    dir = .east(1)
    print(dir)
    
    // 枚舉結(jié)合switc
    switch dir {
    case .east(let value) where (10...20).contains(value):
        print(1)
    case .sourth(let location) where location.x == 10:
        print(location.x)
    default:
        break
    }
}
/// ------------
func 可選項(xiàng)optional() {
    // 類型后面+?
    var name: String? = "jack"
    name = nil
    
    print(name) // Optional(jack)
    
    // 可選值強(qiáng)制解包
    let n = name!
    print(n) // jack
    
    // 可選綁定
    if let number = Int("123123") {
        // number是解包后的值  123123
        
    } else {
        
    }
    // 可選綁定的if語(yǔ)句中 需要使用,分割
    if let a = Int("1"),
       let b = Int("2"),
       a > b {
        print("yes")
    }
    
    // 空合并運(yùn)算符  a??b  , a為可選項(xiàng) b為可選項(xiàng)或者值都可以
    
    var score1: String? = "11"
    var score2: String? = "2"
    print(score1 ?? score2)
    print(score1 ?? 2) // 如果返回score1  那么會(huì)強(qiáng)制解包,因?yàn)楹竺娴氖且粋€(gè)值 非可選項(xiàng)
    
    if let n = score1 ?? score2 {
        // 這種寫(xiě)法等價(jià)于 scrol1 != nil || score2 != nil
    }
    
    if let n = score1,
       let c = score2 {
        // 這種寫(xiě)法等價(jià)于 scrol1 != nil && score2 != nil
    }
    
    // guard語(yǔ)句,當(dāng)條件為false的時(shí)候 會(huì)執(zhí)行括號(hào)里面的代碼
    // guard 條件 else { return、break、continue退出}
    guard let c = Int("adfasf") else {
        print("條件沒(méi)有成立")
        return
    }
    print(c)
    
    // 隱式解包:如果一個(gè)可選值必定有值,可以在類型后面+!
    let s: Int! = Int("123")
    let d: Int = s
    print(d)
    
    // 多重可選項(xiàng)
    let t: Int? = Int("234234")
    let m: Int?? = t // 包裝了一個(gè)可選值的可選值
    
    // 可選項(xiàng)本質(zhì)是枚舉
    enum Optional<T> {
        case same(T)
        case none // nil
    }
     
}
/// ------------


func 結(jié)構(gòu)體struct() {
    // 編譯器會(huì)默認(rèn)給結(jié)構(gòu)體增加一個(gè)初始化器 Initializer, 它的宗旨是保證所有的存儲(chǔ)屬性都有初始值
    struct Date {
        var year: Int
        var month: Int
        var day: Int
    }
    
    let d1 = Date(year: 2022, month: 2, day: 2)
    
    // 自定義初始化器
    struct Datt {
        var year: Int
        var m: Int
        // 自定義初始器,此時(shí)編譯器就不會(huì)生成默認(rèn)初始化器
        init(yy: Int, mm: Int) {
            self.m = mm
            self.year = yy
        }
    }
    
    // let類型的結(jié)構(gòu)體 它的存儲(chǔ)屬性也是let類型不可以修改
    let d = Date(year: 11, month: 1, day: 1)
     // d.day = 22  會(huì)報(bào)錯(cuò)
    
}
/// ------------
func 類class() {
    
    // 編譯器不會(huì)給類生成默認(rèn)初始化器
    class Student {
        var age: Int
        var name: String
        
        init(age: Int, name: String) {
            self.age = age
            self.name = name
        }
    }
    
    let s = Student(age: 1, name: "jack")
    
}
/// ------------
///
func 閉包() {
    // swift中可以使用func來(lái)定義一個(gè)函數(shù),也可以使用閉包來(lái)定義函數(shù)
    
    /*
      閉包格式
      {
        (參數(shù)列表) -> 返回值類型 in
        函數(shù)體代碼
      }
    */
    
    // 使用func定義函數(shù)
    func sum(a: Int, b: Int) -> Int {
        a + b
    }
    
    // 使用閉包定義函數(shù)
    var fuck = {
        (a: Int, b: Int) -> Int in
        a + b
    }
    
    
    let _ = sum(a: 1, b: 2) // 調(diào)用func函數(shù)
    let _ = fuck(2, 4) // 調(diào)用閉包,閉包會(huì)省略參數(shù)標(biāo)簽
    
    // 如果閉包是函數(shù)的最后一個(gè)參數(shù) 可以使用尾隨閉包
    func delete(a: Int, b: Int, fc: (Int ,Int) -> Int) -> Int {
        fc(a, b)
    }
    
    _ = delete(a: 1, b: 2) { a, b in
        a + b
    }
    
    _ = delete(a: 1, b: 3, fc: {
        $0 + $1
    })
}
/// ------------



func 方法() {
    
    // 值類型如果想要在方法中修改屬性  需要使用mutating關(guān)鍵字
    struct DDD {
        var x: Int = 10
        mutating func changeX(a: Int) {
            x = a
        }
    }
    
    class DS {
        // 相當(dāng)于dispatch once
        static let a = "adfaf"
    }
    
    // 消除函數(shù)返回值未使用的警告@discardableResult
    @discardableResult func delete(a: Int, b: Int) -> Int {
        a - b
    }
    
    // 下標(biāo)subscript
    class Person {
        var age: Int = 10
        
        // 下標(biāo)方法可以是類方法  在前面增加static字段即可
        subscript(index: Int) -> Int {
            set {
                if index == 0 {
                    age = newValue
                }
            }
            
            get {
                if index == 0 {
                   return age
                }
                return 3
            }
        }
        
    }
    
}

/// ------------


func 繼承() {
    
    // 類可以繼承,結(jié)構(gòu)體不行
    // 繼承后可以重寫(xiě)父類的方法或者屬性 使用override關(guān)鍵字
    
    class Animal {
        var name = ""
        var age:Int = 10
    }
    
    class Dog: Animal {
        // 重寫(xiě)父類屬性為計(jì)算屬性
        override var name: String {
            set {
                super.name = newValue
            }
            get {
                return ""
            }
            

        }
        
        // 在子類中給父類存儲(chǔ)屬性添加觀察器, 也可以給父類的計(jì)算屬性添加屬性觀察器
        override var age: Int {
            willSet {
                print(newValue)
            }
            
            didSet {
                print(oldValue)
            }
        }
        
        // 被final修飾的屬性 方法,禁止被重寫(xiě)。類禁止被繼承
        
        
    }
    
}

/// ------------

func 初始化構(gòu)造鏈() {
    
    // 父類的屬性在自己的初始化方法中給屬性賦值,不會(huì)觸發(fā)屬性觀察器
    // 父類的屬性 在子類的初始化方法中給屬性賦值,會(huì)觸發(fā)屬性觀察器
    class Animal {
        var age: Int
        
        init(age: Int) {
            self.age = age
        }
    }
    
    class Dog: Animal {
        
        var name: String
        
        init(name: String) {
            // 1. 子類先初始化自己的東西
            self.name = name
            
            // 2. 再調(diào)用父類構(gòu)造方法
            super.init(age: 1)
            
            // 第二階段后 才可以使用self關(guān)鍵字
            
            // 3. 最后可以自定義一些東西
            age = 10
        }
    }
    
    // --------
    
    class Person {
        var age: Int
        // 使用關(guān)鍵字required  那么子類必須繼承或者重寫(xiě)該指定初始化器
        required init(age: Int) {
            self.age = age
        }
    }
    
    class XiaoMing: Person {
        // 子類也必須使用required關(guān)鍵詞重寫(xiě)  不用加override
        required init(age: Int) {
            super.init(age: age)
        }
    }
    
    // -----
    // 可失敗初始化器
    class Bird {
        var age: Int
        init?(age: Int) {
            if age < 0 {
                return nil
            }
            self.age = age
        }
    }
    
    // ------
    // 反初始化器
    class Fish {
        // 先調(diào)用子類的deinit方法,后再調(diào)用父類的deinit方法
        // 父類的反初始化方法可以繼承給子類,即子類銷毀的時(shí)候 會(huì)調(diào)用父類的deinit方法
        deinit {
            print("銷毀了")
            
        }
    }
    
}

func 可選鏈() {
    
    class Person {
        var age: Int = 0
    }
    
    var p: Person? = Person()
    // 結(jié)果是可選項(xiàng) 因?yàn)閜有可能是nil,如果p是nil的情況  那么就不會(huì)繼續(xù)調(diào)用.age方法
    let _ = p?.age
    // 如果本來(lái)就是可選項(xiàng)  那么可選鏈不會(huì)再次包裝 也就是不會(huì)出現(xiàn)??的情況
    
    
    // ----
    // 利用可選鏈有值才會(huì)繼續(xù)向后執(zhí)行的特性
    // 第二行加上?  會(huì)判斷 如果w有值才會(huì)繼續(xù)賦值20, 如果w沒(méi)有值  那么就不會(huì)執(zhí)行后面的賦值操作了
    var w: Int? = 10
    w? = 20
    
    
}

/// ------------

 // 協(xié)議
protocol 協(xié)議 {
    func haha() // 定義方法
    var name: String { get set } // 定義屬性 并聲明可讀可寫(xiě)權(quán)限, 子類可以實(shí)現(xiàn)一個(gè)存儲(chǔ)屬性 也可以是計(jì)算屬性
    var age: String { get }
    subscript(index: Int) -> String { get set }
    // 定義類方法 必須用static關(guān)鍵字 不能使用class,因?yàn)橛锌赡苁墙Y(jié)構(gòu)體遵守這個(gè)協(xié)議
    static func eat()
    mutating func say() // 如果要在方法中修改屬性值,必須在協(xié)議中增加mutating關(guān)鍵字
    
    // 協(xié)議中定義方法不能帶默認(rèn)參數(shù)值
    // 協(xié)議中定義屬性必須用var  不能用let,因?yàn)閷?shí)現(xiàn)的時(shí)候 有可能是計(jì)算屬性 值是不確定的
    // 協(xié)議中聲明的權(quán)限  實(shí)現(xiàn)的時(shí)候可以大于 不能小于,比如是get只讀權(quán)限 實(shí)現(xiàn)的時(shí)候 可以為可讀可寫(xiě)
    
    // 協(xié)議中還可以定義默認(rèn)初始化方法。但是實(shí)現(xiàn)類必須加上required關(guān)鍵字
    init(age: Int)
        
}

protocol hha {
    
}
class PPPPP {
    
}
// 別名
typealias 多組合 = PPPPP & 協(xié)議 & hha
// 協(xié)議組合,要求參數(shù)是指定類型且遵守必要的協(xié)議
func eat(a: 多組合) {
    
}


/// ----------
/// 枚舉遵循CaseIterable協(xié)議  就可以實(shí)現(xiàn)枚舉遍歷
enum Season: CaseIterable {
    case summer
    case winter
}

func 遍歷season() {
    
    for cacse in Season.allCases {
        print(cacse)
    }
}

/// ----------
/// 對(duì)象遵守CustomStringConvertible并實(shí)現(xiàn)description方法 就可以自定義print內(nèi)容
class CustomStringC: CustomStringConvertible {
    var age: Int = 0
    var description: String {
        return "\(age)哈哈"
    }
}


/// --------------
/// swift提供了兩種特殊的類型 Any和AnyObject?;蛘哒f(shuō)是兩種協(xié)議
/// Any可以代表任意類型  枚舉、結(jié)構(gòu)體、類型、函數(shù)
/// AnyObject可以代表任意類類型,不能代表結(jié)構(gòu)體。 如果協(xié)議后面注明AnyObject,表示只有類才能遵守這個(gè)協(xié)議
protocol ClassProtocol: AnyObject {
    
}
class BBB: ClassProtocol {
    
}

var anyArr = Array<Any>() //  存放任意類型的數(shù)組
var anyObjArr = Array<AnyObject>() // 存放任意類的數(shù)組
var anyDic = [Any]()
var anyObjDic = [AnyObject]()


/// --------------
/// is  as  as?  as!
/// is用來(lái)判斷是否是某種類型
/// as用來(lái)做類型轉(zhuǎn)換。 as?表示可選轉(zhuǎn)換,  as!表示強(qiáng)制解包, as表示百分百轉(zhuǎn)換成功  比如as Any時(shí)候可以用as
///
func is_as() {
    
    var a: Any
    a = 10
    if a is Int {
        print("是整型")
    }
    
    class Person {
        func eat() {
            print("eat")
        }
    }
    
    var p: Any = Person()
    // as?拿到的是可選類型 因?yàn)檗D(zhuǎn)換有可能失敗
    // 第二個(gè)?代表是可選鏈調(diào)用eat方法,當(dāng)前面成立 不為nil 才會(huì)調(diào)用eat方法
    (p as? Person)?.eat()
    
}

/// --------------
protocol haha {
    func test() -> Self
}
func self_type_AnyClass() {
    // X是類
    // X.self是一個(gè)元類型的指針,元類型中存放著類的相關(guān)信息,可以稱為元類型 相當(dāng)于oc的class
    // X.self是X.type類型
    class Person {
        required init() {
        }
    }
    
    var typet: Person.Type = Person.self
    // oc中使用class來(lái)創(chuàng)建vc ,在swift中可以使用元類型x.type來(lái)創(chuàng)建
    // [[class alloc] init];
    let _ = Person.self.init()

    func create(type: Person.Type) {
        let _ = type.init()
    }
    
    
    // Self一般用作返回值類型 或者參數(shù)類型,限定返回值必須跟方法調(diào)用者是同一個(gè)類型
    // 類似于oc的instancetype
    
    class Person1: haha {
        required init() {
        }
        
        func test() -> Self {
            return type(of: self).init()
        }
    }
    
    
}


func 錯(cuò)誤error() {
    // swift可以自定義運(yùn)行時(shí)錯(cuò)誤
    // 可以自定義類 遵守Error協(xié)議, 可以是枚舉或者類或者結(jié)構(gòu)體
    enum MyError: Error {
        case local(String)
        case remote(Int)
    }
    
    // 方法需要增加throws關(guān)鍵字
    // 方法內(nèi)部拋出錯(cuò)誤使用throw關(guān)鍵字
    func delete(a: Int, b: Int) throws -> Int {
        
        if a < b {
            throw MyError.local("haha")
        }
        return a - b
    }
    
    // 調(diào)用的時(shí)候  可以使用try  try?   try!
    // 1,調(diào)用時(shí)候一般使用do catch來(lái)捕捉錯(cuò)誤
    do {
        
        print(1)
        var _ = try delete(a: 10, b: 1) // 如果這一步異常了 就不會(huì)執(zhí)行下面print2
        print(2)
        
    } catch let MyError.local(ll) {
        print(ll)
    } catch let MyError.remote(rrr) {
        print(rrr)
    } catch {
        print("兜底")
    }
    
    // 語(yǔ)法糖
    do {
        try delete(a: 10, b: 1)
    } catch let error as MyError {
        print(1)
    } catch is MyError {
        print(23)
    } catch {
        
    }
    
    
    // 2. 調(diào)用方法的時(shí)候 還可以不處理 使用throws繼續(xù)往上拋
    func callDelete() throws {
      var _ =  try delete(a: 10, b: 1) // 如果這一行執(zhí)行報(bào)錯(cuò) 后面print也不會(huì)再執(zhí)行了
        print(3)
    }
    
    // 3.使用try? try!
    var _ = try? delete(a: 10, b: 10) // 返回的是Int?類型  如果正常是可選值Optional(Int)  如果錯(cuò)誤是nil ,跟下面的寫(xiě)法等價(jià)
    do {
        try delete(a: 10, b: 10)
    } catch {
        
    }
    
    // 還可以使用try! 強(qiáng)制解包
    let _ = try! delete(a: 10, b: 10) // 返回值是Int類型
    
    
}


func 懶執(zhí)行defer() {
    // 用來(lái)定義任何方式離開(kāi)前  都必須會(huì)執(zhí)行的代碼,包括return 拋異常error
    defer {
        
    }
}


func 泛型() {
    
    // 1.方法中使用泛型
    // 交換參數(shù)
    func swapValue<T>(a: inout T, b: inout T) {
        (a, b) = (b , a)
    }
    var a = 10
    var b = 2
    swapValue(a: &a, b: &b)
    
    // 把泛型函數(shù)賦值給變量
    let fu: (inout Int, inout Int) -> () = swapValue
    fu(&a, &b)
    
    // 2.類中使用泛型
    class Stack<T> {
        
        var array = [T]()
        func push(t: T) {
            array.append(t)
        }
    }
    // 創(chuàng)建類的時(shí)候 需要顯式標(biāo)明類型
    var s = Stack<Int>()
    // 如果是子類繼承 也需要增加泛型
    class SSStack<T>: Stack<T> {
        
    }
    
    
}


/// ------
func associatedType關(guān)聯(lián)類型() {
    
}

// 給協(xié)議中用到的類型 定義一個(gè)占位名稱,可以簡(jiǎn)單理解協(xié)議中想要實(shí)現(xiàn)泛型  不能用上面的<T>這種方式 只能使用關(guān)聯(lián)類型這種方式
// 協(xié)議中可以定義多個(gè)類型
protocol Stack {
    associatedtype element

    mutating func push(e: element)
}

// 遵守協(xié)議的時(shí)候, 可以通過(guò)typealias來(lái)指定類型,也可以省略typealias 讓編譯器自己根據(jù)我們寫(xiě)的方法類型判斷
class BBBB: Stack {
    typealias element = Int
    func push(e: Int) {
        print(1)
    }
}

/// -------- 類型約束
/// 約束泛型t的類型或者必須遵守協(xié)議
func mutal<T: PPPPP & Stack>(a: T) -> T {
    return a
}
/// 約束協(xié)議中的泛型必須遵守協(xié)議
protocol Hadaf {
    associatedtype T: Stack
}

// 還可以在func中增加where語(yǔ)句做更細(xì)致的類型約束
func aasdfas<T, M>(a: T, b: M) where T == M {
    
}
/// some 限制只能返回一種類型,不透明協(xié)議
protocol Masdfasf {
    associatedtype T
}
class Flya: Masdfasf {
    typealias T = Int
}
class FlaB: Masdfasf {
    typealias T = Double
}

func getf(a: Int) -> some Masdfasf { // 限制方法內(nèi)部 只能返回一種遵守Masdfasf的類型 不能返回兩種
    return FlaB()
}


///-------- 溢出運(yùn)算符
/// swift支持溢出運(yùn)算 &+  &-  &*
var max = Int8.max
var mmm = max + 1 // 會(huì)崩潰 因?yàn)橐绯隽?var mmmm = max &+ 1 // 不會(huì)崩潰  但是會(huì)變成最小值 因?yàn)橐绯隽?

///-------- 運(yùn)算符重載
struct HhhAAA {
    // 運(yùn)算符重載方法 需要增加static關(guān)鍵字
    static func +(a: HhhAAA, b: HhhAAA) -> HhhAAA {
        return a
    }
    
    static func +=(a: HhhAAA, b: HhhAAA) -> HhhAAA {
        return a
    }
    
}
/// equatable協(xié)議 就是重載==運(yùn)算符
class Eafafd: Equatable {
    var name: Int = 0
    static func ==(lhs: Eafafd, rhs: Eafafd) -> Bool {
        return lhs.name == rhs.name
    }
}

/// Comparable協(xié)議 用來(lái)重載<實(shí)現(xiàn)比較大小
//class ASDFAFD: Comparable {
//    static func < (lhs: ASDFAFD, rhs: ASDFAFD) -> Bool {
//        return true
//    }
//
//}


/// 自定義運(yùn)算符  使用operator關(guān)鍵字
///
/// ------------  拓展 entension,類似于oc的分類
/// 可以添加方法、計(jì)算屬性、下標(biāo)、(便捷)初始化器、嵌套類型、協(xié)議等等
//擴(kuò)展不能辦到的事情:
//  口不能覆蓋原有的功能
//  口不能添加存儲(chǔ)屬性,不能向已有的屬性添加屬性觀察器
//  口不能添加父類
//  口不能添加指定初始化器,不能添加反初始化器
class Paer {
}
extension Paer {
}


/// ------------  訪問(wèn)控制 權(quán)限控制
/// 訪問(wèn)權(quán)限控制這塊,Swift提供了5個(gè)不同的訪問(wèn)級(jí)別(以下是從高到低排列,實(shí)體指被訪問(wèn)級(jí)別修飾的內(nèi)容)
/// 模塊可以理解為一個(gè)可執(zhí)行文件  target,一個(gè)動(dòng)態(tài)庫(kù)或者靜態(tài)庫(kù)是一個(gè)模塊
//口open:允許在定義實(shí)體的模塊、其他模塊中訪問(wèn),允許其他模塊進(jìn)行繼承、重寫(xiě)(open只能用在類、類成員上)
//口public:允許在定義實(shí)體的模塊、其他模塊中訪問(wèn),不允許其他模塊進(jìn)行繼承、重寫(xiě)
//口internal:只允許在定義實(shí)體的模塊中訪問(wèn),不允許在其他模塊中訪問(wèn)
//口fileprivate:只允許在定義實(shí)體的源文件中訪問(wèn)
//口private:只允許在定義實(shí)體的封閉聲明中訪問(wèn)

//訪問(wèn)級(jí)別的使用準(zhǔn)則
//一個(gè)實(shí)體不可以被更低訪問(wèn)級(jí)別的實(shí)體定義,比如
//變量\常量類型 >= 變量\常量
//口參數(shù)類型、返回值類型  >= 函數(shù)
//父類子類 >= 父協(xié)議子協(xié)議
//原類型  >=  typealias
//原始值類型、關(guān)聯(lián)值類型 >= 枚舉類型
//定義類型A時(shí)用到的其他類型 >= 類型A



/// ----- 內(nèi)存管理 weak  unowned
/// weak定義的必須是可選類型的var 因?yàn)殇N毀后arc會(huì)自動(dòng)把該弱引用置為nil  類似于oc的weak
/// unowned 類似于oc的assing  對(duì)象銷毀后還保存著該指針 再次訪問(wèn)容易引發(fā)野指針崩潰
// 如果想在定義閉包屬性的同時(shí)引用self,這個(gè)閉包必須是lazy的(因?yàn)樵趯?shí)例初始化完畢之后才能引用self)

func weakUnowned() {
    class Person {
        //左邊的閉包fn內(nèi)部如果用到了實(shí)例成員(屬性、方法)
        lazy var fn: (() ->()) = {
            [weak self] in
            //口編譯器會(huì)強(qiáng)制要求明確寫(xiě)出self
            self?.run()
        }
        func run() { print("run") }
        deinit { print("deinit") }
    }
    
    //如果lazy屬性是閉包調(diào)用的結(jié)果,那么不用考慮循環(huán)引用的問(wèn)題(因?yàn)殚]包調(diào)用后,閉包的生命周期就結(jié)束了)
    class Person1 {
        var age: Int = 0
        lazy var getAge: Int = {
            self.age
        }()
    }
}

///---------- 逃逸閉包escaping
///逃逸閉包、逃逸閉包,一般都是當(dāng)做參數(shù)傳遞給函數(shù)
///非逃逸閉包:閉包調(diào)用發(fā)生在函數(shù)結(jié)束前,閉包調(diào)用在函數(shù)作用域內(nèi)
///逃逸閉包:閉包有可能在函數(shù)結(jié)束后調(diào)用,閉包調(diào)用逃離了函數(shù)的作用域,需要通過(guò)@escaping聲明
///
func 逃逸閉包escaping() {
    typealias Fn = () -> ()
    //fn是非逃逸閉包
    func test1(_ fn: Fn) { fn() }
 
    //fn是逃逸閉包
    var gFn: Fn?
    func test2(_ fn: @escaping Fn) { gFn = fn }
}

///---------- 局部作用域  do, 類似于oc的{  }
func 局部作用域do() {
    
    do {
        var a = 10
    }
    
    do {
        var a = 2
    }
    
}


/// ------ 指針
func pointer() {
    
    func unsafePointer(a: UnsafePointer<Int>) {
        print(a.pointee)
    }
    
    func unsafeMPointer(a: UnsafeMutablePointer<Int>) {
        a.pointee = 20
    }
    
    var b = 10
    unsafePointer(a: &b)
    unsafeMPointer(a: &b)
    
//    Swift中也有專門(mén)的指針類型,這些都被定性為“Unsafe”(不安全的),常見(jiàn)的有以下4種類型:
//     UnsafePointer<Pointee>似 const Pointee *, 不可修改 只能訪問(wèn)
//     UnsafeMutablePointer<Pointee>似 Pointee *  ,可以修改指針指向的內(nèi)容
//     UnsafeRawPointer似 const void *
//     UnsafeMutableRawPointer 類似 void *
    
}


/// ---- 通配符
///  _ 匹配任何值
///  _? 匹配非nil值  針對(duì)可選項(xiàng)來(lái)說(shuō)
///
func 通配符() {
    
    enum Price {
        case a(Int, Int?)
        case b(Double?)
    }
    
    var c = Price.a(10, 10)
    
    switch c {
    case .a(let first, _): // 第二個(gè)值nil或者有值都可以
        print(first)
        
    case .b(_?): // 匹配非空
        print("afa")
    default:
        break
    }
    
}



/// ---- 枚舉case模式
///
func enumcase() {
    
    var age = 10
    
    // if case等價(jià)于只有一個(gè)case的switch語(yǔ)句
    if case 0...9 = age {
        print("haha")
    }
    
    switch age {
    case 0...9:
        print("haha")
        
    default: break
    }
    
    
    // guard case模式
    guard case 0..<10 = age else {
        
        return
    }
    

}


/// ------ 注釋
func 注釋() {
    // FIXME: ADF
    // TODO: HAHD
    // MARK: ASDFAF
    // MARK: - ADFASF
    
}


/// --- oc調(diào)用swift
func oc調(diào)用swift() {
    
    @objc(NewClass) // 可以使用@objc自定義方法名和類名
    @objcMembers class Caaa: NSObject { // 需要繼承自NSObject
        // @objcMembers可以把所有方法和屬性都暴露給oc  相當(dāng)于每個(gè)成員前面都增加@objc
        
        @objc func callrun() {
            perform(#selector(run))
            perform(#selector(run(a:)))
        }
        
        
        @objc  func run(a: Int) {
            
            
        }
        
    }
}


/// --- string  substring 字符串處理
func stringt() {
    
    // String可以通過(guò)下標(biāo)、prefix、 suffix等截取子串,子串類型不是String,而是Substring
    var str = "1_2_3_4_5"
    //1_2
    var substr1 = str.prefix(3)
    var substr2 = str.suffix(3)
    var range = str.startIndex..<str.index(str.startIndex, offsetBy: 3)
    var substr3 = str[range]
    
    //最初的String,1_2_3_4_5
    print(substr3.base)
    
    // Substring -> String
    var str2 = String(substr3)
}



/// ------ swift 支持kvc kvo
/// 類需要繼承自nsobject
/// 用@objc dynamic來(lái)修飾屬性
///
///
///
/// ------ swift 關(guān)聯(lián)對(duì)象 給拓展增加存儲(chǔ)屬性
class Prer {
}

extension Prer {
    
    private static var nameKey = true // 使用void?也行   因?yàn)槎颊加靡粋€(gè)字節(jié)
    
    var name: Int {
        get {
            objc_getAssociatedObject(self, &Self.nameKey) as! Int
        }
        
        set {
            objc_setAssociatedObject(self, &Prer.nameKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
        
    }
    
}

/// ------ 可選項(xiàng)的map和flatMap
/// map和flatMap會(huì)先判斷 如果是非nil才會(huì)繼續(xù)執(zhí)行,flatMap區(qū)別是會(huì)判斷已經(jīng)是可選項(xiàng)了 就不會(huì)再次包裝   即不會(huì)出現(xiàn)??的情況
func optionalMap() {
    var age: Int? = 10
    var b = age.flatMap {
        $0 + 1
    }
    print(b as Any)
}

?著作權(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)容