美文网首页
Swift随笔

Swift随笔

作者: leblanc_i | 来源:发表于2020-11-18 11:30 被阅读0次

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

    一、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: 类似于OC中的 #pragma mark
    • MARK: - 类似于OC中的 #pragma mark - (预览的时候跟上个相同级别的标注之间会有线隔开,见下面图片中灰色线条)
    • TODO: 用于标记未完成的任务
    • FIXME: 用于标记待修复的问题
    • warning("undo"):如果觉得 TODO: 不够明显, 可以考虑用这个

        // 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
    

    十二、属性

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

    • 实例属性(Instance Property)
      1.存储实例属性(Stored Instance Property)存储在实例的内存中,每个实例都有1份
      2.计算实例属性(Computed Instance Property)

    • 类型属性(Type Property)
      1.存储类型属性(Stored Type Property)整个程序运行过程中,就只有1份内存(类似于全局变量)
      2.计算类型属性(Computed Type Property)

    十三、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

    • Any:可以代表任意类型(枚举、结构体、类、也包括函数类型)
    • AnyObject:可以代表任意 类 类型(在协议后面加上: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个不同的访问级别,以下是从高到低排列,实体指的是被访问级别修饰的内容

    • open:允许在定义实体的模块,其它模块中访问,允许其它模块进行继承、重写(open只能用在类、类成员上)
    • public:允许在定义实体的模块、其它模块中访问、不允许其它模块进行继承、重写
    • internal:只允许在定义实体的模块中访问,不允许在其它模块中访问
    • fileprivate:只允许在定义实体的源文件中访问
    • private:只允许在定义实体的封闭声明中访问

    注:绝大部分实体默认都是 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()
    
    

    相关文章

      网友评论

          本文标题:Swift随笔

          本文链接:https://www.haomeiwen.com/subject/dgaqiktx.html