Swift隨筆

簡(jiǎn)單記錄一些自己容易忘記的碎片化的點(diǎn)

一、tips

1、swift中文名雨燕
2、不用編寫main函數(shù),將全局范圍內(nèi)首句可執(zhí)行代碼作為程序入口
3、一句代碼尾部可以省略分號(hào),多句代碼寫到同一行必須用分號(hào)隔開
4、var定義變量,let定義常量,編譯器能夠自動(dòng)推斷出變量和常量的類型

二、常見數(shù)據(jù)類型

Swift常見數(shù)據(jù)類型.png

三、函數(shù)文檔注釋

    ///
    /// 求和【概述】
    ///
    ///  將兩個(gè)整數(shù)相加【更加詳細(xì)的描述】
    ///
    /// - Parameter a: 參數(shù)a描述
    /// - Parameter b: 參數(shù)b描述
    /// - Returns :兩個(gè)整數(shù)的和
    ///
    /// - Note:傳入兩個(gè)整數(shù)即可【批注】
    ///
    func sum(a: Int, b: Int) -> Int {
        a + b
    }

調(diào)用的時(shí)候,按住option,點(diǎn)擊函數(shù)名即可出現(xiàn)下圖的注釋效果:


注釋.png

MARK / TODO / FIXME

  • MARK: 類似于OC中的 #pragma mark
  • MARK: - 類似于OC中的 #pragma mark - (預(yù)覽的時(shí)候跟上個(gè)相同級(jí)別的標(biāo)注之間會(huì)有線隔開,見下面圖片中灰色線條)
  • TODO: 用于標(biāo)記未完成的任務(wù)
  • FIXME: 用于標(biāo)記待修復(fù)的問(wèn)題
  • warning("undo"):如果覺(jué)得 TODO: 不夠明顯, 可以考慮用這個(gè)

    // MARK: - 私有方法
    
    // MARK: test1方法
    private func test1() {
        // TODO: 未完成
    }
    
    // MARK: test2方法
    private func test2() {
        // FIXME: 有待修復(fù)的問(wèn)題
    }
    
    
    // MARK: - 公共方法
    
    // MARK: test3方法
    public func test3() {}
    
    // MARK: test4方法
    public func test4() {}
    
    // 警告,會(huì)在代碼中有明顯的黃色嘆號(hào)提示
    #warning("undo")

注釋.png

四、參數(shù)

1、可以修改參數(shù)標(biāo)簽

    func gotoSchool(at time: String) {
        print("go to school \(time)")
    }
    gotoSchool(at: "08:00")

2、可以使用下劃線_ 省略參數(shù)標(biāo)簽,相對(duì)復(fù)雜的盡量不要省略

    func sum(_ a: Int, _ b: Int) -> Int {
        a + b
    }
    print(sum(10, 20))

3、參數(shù)類型后面加上三個(gè)點(diǎn)表示可變參數(shù),可以傳多個(gè)對(duì)應(yīng)類型的參數(shù)

需要注意的問(wèn)題:
1、一個(gè)函數(shù)最多只能有一個(gè)可變參數(shù)
2、緊跟在可變參數(shù)后面的參數(shù)不能省略參數(shù)標(biāo)簽

    func sum(_ numbers: Int...) -> Int {
        var total = 0
        for number in numbers {
            total += number
        }
        return total
    }
    print(sum(10, 20, 30, 40)) // 100

五、Optional-可選項(xiàng)

可選項(xiàng),一般也叫可選類型,它允許將值設(shè)置為nil,在類型名稱后面加個(gè)?來(lái)定義一個(gè)可選項(xiàng)

        var name: String? = "Jack"http:// 不寫= "Jack",默認(rèn)就是nil
        name = nil

可選項(xiàng)是對(duì)其它類型的一層包裝,如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù),需要使用感嘆號(hào)!進(jìn)行強(qiáng)制解包

        let count: Int? = 10
        var countAdd: Int = count!
        countAdd += 10
        print(countAdd)

如果對(duì)值為nil的可選項(xiàng)進(jìn)行強(qiáng)制解包,會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤,程序直接崩潰

        let count: Int?
        // 如果count為nil,強(qiáng)制解包程序會(huì)crash
        count!
        // 在實(shí)際開發(fā)中我們一般會(huì)這樣做
        if let temp = count {
            // 在這里進(jìn)行處理
            print(temp)
        }

可選項(xiàng)的本質(zhì)是 enum 類型,下面兩種寫法完全等價(jià)

        let a: Int? = 10
        
        let b: Optional<Int> = .some(10)

六、運(yùn)算符

1、??:合并空值運(yùn)算符

        a ?? b

(1)用于判斷常量或者變量的值是否為nil,如果為nil,則取后面的值,不為nil,取前面的值。有點(diǎn)兒類似三目運(yùn)算符
(2)上面的表達(dá)式,如果a有值,則取a,如果a為nil,則取b

應(yīng)用示例:

    func sum(a: Int?, b: Int?) -> Int {
        
        // 方法一:如果a或者b有nil,則程序會(huì)crash
        return a! + b!
        
        //方法二:判斷條件太多,容易遺漏
        if a != nil {
            if b != nil {
                return a! + b!
            } else {
                return a!
            }
        } else {
            if b != nil {
                return b!
            } else {
                return 0
            }
        }
        
        //方法三:簡(jiǎn)潔、安全
        return (a ?? 0) + (b ?? 0)
        
    }

2、reversed():倒序索引

        for i in (0...9).reversed() {
            print(i)
        }
        // 輸出結(jié)果
        9
        8
        7
        6
        5
        4
        3
        2
        1
        0

3、\color{red}{,} (逗號(hào))

做判斷的時(shí)候在兩個(gè)條件中間加一個(gè) \color{red}{,} 相當(dāng)于 &&

        let  a: Int = 11

        // 判斷1 和 判斷2 等價(jià)
        // 判斷1
        if a > 0, a > 11 {
            print(123)
        }
        // 判斷2
        if a > 0 && a > 11 {
            print(123)
        }
    

七、guard

guard語(yǔ)句,有點(diǎn)兒類似if語(yǔ)句,但是后面會(huì)一直跟著else語(yǔ)句,并且else里面的語(yǔ)句只有在guard條件不為真的時(shí)候才執(zhí)行。下面兩段代碼是檢測(cè)ip地址是否正確,第一段用if實(shí)現(xiàn),第二段用guard實(shí)現(xiàn)。

    // 試用if判斷ip地址是否正確
    func checkIpAddress(ipAddress: String) -> (Int, String) {
        // 用點(diǎn)來(lái)分割ip地址
        let compoment = ipAddress.split(separator: ".")
        if compoment.count == 4 {
            if let first = Int(compoment[0]), first >= 0 && first < 256 {
                if let second = Int(compoment[1]), second >= 0 && second < 256 {
                    if let third = Int(compoment[2]), third >= 0 && third < 256 {
                        if let fourth = Int(compoment[3]), fourth >= 0 && fourth < 256 {
                            return (100, "ip地址是正確的")
                        } else {
                            return (4, "ip地址第四部分不對(duì)")
                        }
                    } else {
                        return (3, "ip地址第三部分不對(duì)")
                    }
                } else {
                    return (2, "ip地址第二部分不對(duì)")
                }
            } else {
                return (1, "ip地址第一部分不對(duì)")
            }
        } else {
            return (0, "ip地址必須有四部分")
        }
    }
    // 試用guard判斷ip地址是否正確
    func checkIpAddress(ipAddress: String) -> (Int, String) {
        let compoment = ipAddress.split(separator: ".")
        
        guard compoment.count == 4 else {
            return (0, "ip地址必須有四部分")
        }
        
        guard let first = Int(compoment[0]), first >= 0 && first < 256 else {
            return (1, "ip地址第一部分不對(duì)")
        }
        
        guard let second = Int(compoment[1]), second >= 0 && second < 256 else {
            return (2, "ip地址第二部分不對(duì)")
        }
        
        guard let third = Int(compoment[2]), third >= 0 && third < 256 else {
            return (3, "ip地址第三部分不對(duì)")
        }
        
        guard let fourth = Int(compoment[3]), fourth >= 0 && fourth < 256 else {
            return (4, "ip地址第四部分不對(duì)")
        }
        
        return (100, "ip地址是正確的")
    }

八、字符串

1、首字母大寫:capitalized

        let str = "hello world"
        print(str.capitalized)
        // 輸出:Hello World

2、字符全部轉(zhuǎn)大寫

        let str = "hello world"
        print(str.uppercased())
        // 輸出:HELLO WORLD

3、字符全部轉(zhuǎn)小寫

        let str = "HeLLo WoRlD"
        print(str.lowercased())
        // 輸出:hello world

九、數(shù)組

1、以逗號(hào)拼接字符串?dāng)?shù)組所有元素為一個(gè)字符串

        let arr = ["you", "only", "live", "once"]
        let newArr = arr.joined(separator: ",")
        print(newArr)
        // 輸出
        you,only,live,once

2、字符串轉(zhuǎn)數(shù)組

        let str = "you only live once"
        let arr = str.components(separatedBy: " ")
        print(arr)
        // 輸出
        ["you", "only", "live", "once"]

十、輸入輸出參數(shù)(In-Out Parameter)

可以用inout定義一個(gè)輸入輸出參數(shù),在函數(shù)內(nèi)部修改外部變量的值
inout的本質(zhì)是地址傳遞(引用傳遞)
inout參數(shù)不能有默認(rèn)值
可變參數(shù)不能標(biāo)記為inout
inout參數(shù)的傳入值能被多次賦值

        func swapValue(_ v1: inout Int, _ v2: inout Int) {
            let tmp = v1
            v1 = v2
            v2 = tmp
        }
        
        var num1 = 10
        var num2 = 20
        swapValue(&num1, &num2)
        print(num1, num2)
        // 打印結(jié)果
        // 20 10

十一、可變參數(shù)

參數(shù)類型后面加三個(gè)點(diǎn)表示可變參數(shù)
一個(gè)函數(shù)最多只能有1個(gè)可變參數(shù)
緊跟在可變參數(shù)后面的參數(shù)不能省略參數(shù)標(biāo)簽

    func sum(_ numbers: Int..., other: Int) -> Int {
        var total = 0
        for item in numbers {
            total += item
        }
        return total + other
    }
    let result = sum(1, 2, 3, 4, other: 5)
    print(result)
    // 打印結(jié)果
    // 15

十二、屬性

嚴(yán)格來(lái)說(shuō),屬性可以按下面方式劃分

  • 實(shí)例屬性(Instance Property)
    1.存儲(chǔ)實(shí)例屬性(Stored Instance Property)存儲(chǔ)在實(shí)例的內(nèi)存中,每個(gè)實(shí)例都有1份
    2.計(jì)算實(shí)例屬性(Computed Instance Property)

  • 類型屬性(Type Property)
    1.存儲(chǔ)類型屬性(Stored Type Property)整個(gè)程序運(yùn)行過(guò)程中,就只有1份內(nèi)存(類似于全局變量)
    2.計(jì)算類型屬性(Computed Type Property)

十三、mutating

結(jié)構(gòu)體和枚舉是值類型,默認(rèn)情況下,值類型的屬性不能被自身的實(shí)例方法修改
在 func 關(guān)鍵字前加 mutating 可以允許這種修改行為

    // 結(jié)構(gòu)體
    struct Point {
        var x = 0.0, y = 0.0
        mutating func moveBy(_ deltaX: Double, _ deltaY: Double) {
            x += deltaX
            y += deltaY
        }
    }
    // 枚舉
    enum StateSwitch {
        case low, middle, high
        mutating func next() {
            switch self {
            case .low:
                self = .middle
            case .middle:
                self = .high
            case .high:
                self = .low
            }
        }
    }

十四、@discardableResult

調(diào)用有返回值的方法,如果沒(méi)有使用返回的值,會(huì)有一個(gè)黃色的警告,如果想消除這個(gè)警告,可以在方法前面加上 @discardableResult
注:除非特殊需求,建議非必要不要使用

    @discardableResult func add(_ a: Int, _ b: Int) -> Int {
        a + b
    }
    // 這樣直接調(diào)用就不會(huì)有警告了
    add(10, 3)

十五、class & static & final

1、被class修飾的類型方法、下標(biāo),允許被子類重寫
被static修飾的類型方法、下標(biāo),不允許被子類重寫
2、被class修飾的計(jì)算類型屬性,可以被子類重寫
被static修飾的類型屬性(存儲(chǔ)、計(jì)算),不可以被子類重寫
3、被 final 修飾的方法、下標(biāo)、屬性,禁止被重寫
被final修飾的類,禁止被繼承

十六、(+) (-)

Swift 編譯器特性

        // 兩個(gè) Int 類型參數(shù)相加、相減
        let dic: [String: (Int, Int) -> Int] = [
            "sum": (+),
            "minus": (-)
        ]
        
        let result1 = dic["sum"]?(10, 5)
        let result2 = dic["minus"]?(12, 5)
        
        print(result1)
        print(result2)

十七、Any / AnyObject

  • Any:可以代表任意類型(枚舉、結(jié)構(gòu)體、類、也包括函數(shù)類型)
  • AnyObject:可以代表任意 類 類型(在協(xié)議后面加上:AnyObject,代表只有類能遵守和這個(gè)協(xié)議)

十八、數(shù)組、字典聲明

        // 下面兩種聲明數(shù)組的方法完全等價(jià)
        var arr = Array<Int>()
        var arr = [Int]()

        // 下面兩種聲明字典的方法完全等價(jià)
        var dic = Dictionary<Int, Int>()
        var dic = [Int: Int]()

十九、is、as、as?、 as!

i s 用來(lái)判斷是否為某種類型, as用來(lái)做類型強(qiáng)制轉(zhuǎn)換

二十、訪問(wèn)控制(Access Control)

在訪問(wèn)權(quán)限控制這塊,Swift提供了5個(gè)不同的訪問(wèn)級(jí)別,以下是從高到低排列,實(shí)體指的是被訪問(wèn)級(jí)別修飾的內(nèi)容

  • open:允許在定義實(shí)體的模塊,其它模塊中訪問(wèn),允許其它模塊進(jìn)行繼承、重寫(open只能用在類、類成員上)
  • public:允許在定義實(shí)體的模塊、其它模塊中訪問(wèn)、不允許其它模塊進(jìn)行繼承、重寫
  • internal:只允許在定義實(shí)體的模塊中訪問(wèn),不允許在其它模塊中訪問(wèn)
  • fileprivate:只允許在定義實(shí)體的源文件中訪問(wèn)
  • private:只允許在定義實(shí)體的封閉聲明中訪問(wèn)

注:絕大部分實(shí)體默認(rèn)都是 internal 級(jí)別

二十一、API可用性說(shuō)明

比如你自己封裝了一個(gè)三方框架,但是在升級(jí)過(guò)程中有的API被廢棄掉,或者已過(guò)期,可以進(jìn)行下面的操作

struct Student {
    
    // 方法名重命名
    @available(*, unavailable, renamed: "study")
    func study1() {}
    func study() {}
    
    // 方法在iOS被廢棄掉
    @available(iOS, deprecated: 11)
    func run() {}
}

        let stu = Student()
        // 會(huì)提示 'run()' was deprecated in iOS 11
        stu.run()
        // 會(huì)提示 'study1()' has been renamed to 'study'
        stu.study1()

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容