Swift随笔

2020-11-18  本文已影响0人  leblanc_i

简单记录一些自己容易忘记的碎片化的点

一、tips

1、swift中文名雨燕
2、不用编写main函数,将全局范围内首句可执行代码作为程序入口
3、一句代码尾部可以省略分号,多句代码写到同一行必须用分号隔开
4、var定义变量,let定义常量,编译器能够自动推断出变量和常量的类型

二、常见数据类型

Swift常见数据类型.png

三、函数文档注释

    ///
    /// 求和【概述】
    ///
    ///  将两个整数相加【更加详细的描述】
    ///
    /// - Parameter a: 参数a描述
    /// - Parameter b: 参数b描述
    /// - Returns :两个整数的和
    ///
    /// - Note:传入两个整数即可【批注】
    ///
    func sum(a: Int, b: Int) -> Int {
        a + b
    }

调用的时候,按住option,点击函数名即可出现下图的注释效果:


注释.png

MARK / TODO / FIXME

    // MARK: - 私有方法
    
    // MARK: test1方法
    private func test1() {
        // TODO: 未完成
    }
    
    // MARK: test2方法
    private func test2() {
        // FIXME: 有待修复的问题
    }
    
    
    // MARK: - 公共方法
    
    // MARK: test3方法
    public func test3() {}
    
    // MARK: test4方法
    public func test4() {}
    
    // 警告,会在代码中有明显的黄色叹号提示
    #warning("undo")

注释.png

四、参数

1、可以修改参数标签

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

2、可以使用下划线_ 省略参数标签,相对复杂的尽量不要省略

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

3、参数类型后面加上三个点表示可变参数,可以传多个对应类型的参数

需要注意的问题:
1、一个函数最多只能有一个可变参数
2、紧跟在可变参数后面的参数不能省略参数标签

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

五、Optional-可选项

可选项,一般也叫可选类型,它允许将值设置为nil,在类型名称后面加个?来定义一个可选项

        var name: String? = "Jack"// 不写= "Jack",默认就是nil
        name = nil

可选项是对其它类型的一层包装,如果要从可选项中取出被包装的数据,需要使用感叹号!进行强制解包

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

如果对值为nil的可选项进行强制解包,会产生运行时错误,程序直接崩溃

        let count: Int?
        // 如果count为nil,强制解包程序会crash
        count!
        // 在实际开发中我们一般会这样做
        if let temp = count {
            // 在这里进行处理
            print(temp)
        }

可选项的本质是 enum 类型,下面两种写法完全等价

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

六、运算符

1、??:合并空值运算符

        a ?? b

(1)用于判断常量或者变量的值是否为nil,如果为nil,则取后面的值,不为nil,取前面的值。有点儿类似三目运算符
(2)上面的表达式,如果a有值,则取a,如果a为nil,则取b

应用示例:

    func sum(a: Int?, b: Int?) -> Int {
        
        // 方法一:如果a或者b有nil,则程序会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
            }
        }
        
        //方法三:简洁、安全
        return (a ?? 0) + (b ?? 0)
        
    }

2、reversed():倒序索引

        for i in (0...9).reversed() {
            print(i)
        }
        // 输出结果
        9
        8
        7
        6
        5
        4
        3
        2
        1
        0

3、\color{red}{,} (逗号)

做判断的时候在两个条件中间加一个 \color{red}{,} 相当于 &&

        let  a: Int = 11

        // 判断1 和 判断2 等价
        // 判断1
        if a > 0, a > 11 {
            print(123)
        }
        // 判断2
        if a > 0 && a > 11 {
            print(123)
        }
    

七、guard

guard语句,有点儿类似if语句,但是后面会一直跟着else语句,并且else里面的语句只有在guard条件不为真的时候才执行。下面两段代码是检测ip地址是否正确,第一段用if实现,第二段用guard实现。

    // 试用if判断ip地址是否正确
    func checkIpAddress(ipAddress: String) -> (Int, String) {
        // 用点来分割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地址第四部分不对")
                        }
                    } else {
                        return (3, "ip地址第三部分不对")
                    }
                } else {
                    return (2, "ip地址第二部分不对")
                }
            } else {
                return (1, "ip地址第一部分不对")
            }
        } 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地址第一部分不对")
        }
        
        guard let second = Int(compoment[1]), second >= 0 && second < 256 else {
            return (2, "ip地址第二部分不对")
        }
        
        guard let third = Int(compoment[2]), third >= 0 && third < 256 else {
            return (3, "ip地址第三部分不对")
        }
        
        guard let fourth = Int(compoment[3]), fourth >= 0 && fourth < 256 else {
            return (4, "ip地址第四部分不对")
        }
        
        return (100, "ip地址是正确的")
    }

八、字符串

1、首字母大写:capitalized

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

2、字符全部转大写

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

3、字符全部转小写

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

九、数组

1、以逗号拼接字符串数组所有元素为一个字符串

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

2、字符串转数组

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

十、输入输出参数(In-Out Parameter)

可以用inout定义一个输入输出参数,在函数内部修改外部变量的值
inout的本质是地址传递(引用传递)
inout参数不能有默认值
可变参数不能标记为inout
inout参数的传入值能被多次赋值

        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)
        // 打印结果
        // 20 10

十一、可变参数

参数类型后面加三个点表示可变参数
一个函数最多只能有1个可变参数
紧跟在可变参数后面的参数不能省略参数标签

    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)
    // 打印结果
    // 15

十二、属性

严格来说,属性可以按下面方式划分

十三、mutating

结构体和枚举是值类型,默认情况下,值类型的属性不能被自身的实例方法修改
在 func 关键字前加 mutating 可以允许这种修改行为

    // 结构体
    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

调用有返回值的方法,如果没有使用返回的值,会有一个黄色的警告,如果想消除这个警告,可以在方法前面加上 @discardableResult
注:除非特殊需求,建议非必要不要使用

    @discardableResult func add(_ a: Int, _ b: Int) -> Int {
        a + b
    }
    // 这样直接调用就不会有警告了
    add(10, 3)

十五、class & static & final

1、被class修饰的类型方法、下标,允许被子类重写
被static修饰的类型方法、下标,不允许被子类重写
2、被class修饰的计算类型属性,可以被子类重写
被static修饰的类型属性(存储、计算),不可以被子类重写
3、被 final 修饰的方法、下标、属性,禁止被重写
被final修饰的类,禁止被继承

十六、(+) (-)

Swift 编译器特性

        // 两个 Int 类型参数相加、相减
        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

十八、数组、字典声明

        // 下面两种声明数组的方法完全等价
        var arr = Array<Int>()
        var arr = [Int]()

        // 下面两种声明字典的方法完全等价
        var dic = Dictionary<Int, Int>()
        var dic = [Int: Int]()

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

i s 用来判断是否为某种类型, as用来做类型强制转换

二十、访问控制(Access Control)

在访问权限控制这块,Swift提供了5个不同的访问级别,以下是从高到低排列,实体指的是被访问级别修饰的内容

注:绝大部分实体默认都是 internal 级别

二十一、API可用性说明

比如你自己封装了一个三方框架,但是在升级过程中有的API被废弃掉,或者已过期,可以进行下面的操作

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

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

上一篇 下一篇

猜你喜欢

热点阅读