Swift 学习一函数&函数属性&懒加载

函数
  • 函数相当于OC中的方法
  • 格式:
    • func 函数名(参数列表) -> 返回值类型 {
          代码块
          return 返回值
      }
    • func 函数名(参数列表){  // 返回值为Void 可以省略
          代码块
          return 返回值
      }
 
  • 常见函数类型
    • // 1.没有参数,没用返回值
      func run() -> Void {
          print("I am running")
      }

      // 如果没用返回值,Void可以写成()
      func run1() -> () {
          print("I am running")
      }
      // 如果没有返回值,后面的内容可以都不写
      func run2() {
          print("I am running")
      }

      // 调用函数
      run2()

      // 2.有参数,没用返回值
      func callPhone(phoneNum : String) {
          print("打电话给(phoneNum)")
      }
      callPhone("10086")

      // 3.没用参数,有返回值
      func greetings() -> String {
          return "吃饭了吗?"
      }
      var str1 = greetings()
      print(str1)

      // 4.有参数,有返回值
      func sum(num1 : Int, num2 : Int) -> Int {
          return num1 + num2
      }
      var result = sum(20, num2: 30)
      print(result)
  • 函数使用注意
    • 在函数内部可以看到的参数,就是内部参数
    • 在函数外面可以看到的参数,就是外部参数
    • 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
    • 如果第一个参数也想要有外部参数,可以设置标签:在变量名前加标签即可
    • 如果不想要外部参数,可以在参数名称前加_
      • // 默认情况下,从第二个参数开始,参数名称既是内部参数也是外部参数
        func calculate(num1 : Int, num2 : Int, num3 : Int) -> Int {
            return num1 * num2 * num3
        }
        var result1 = calculate(20, num2: 4, num3: 5)

        // 如果第一个参数也想要有外部参数,在变量名前加标签即可,如果不想要,在参数名前加 _
        func calculate1(myNum1 num1 : Int, _ num2 : Int, num3 : Int) -> Int {
            return num1 * num2 * num3
        }
        var result2 = calculate1(myNum1: 20, 4, num3: 5)

        // 方法的重载:方法名称相同,但是参数不同,可以称之为方法的重载
        func calculate(num1: Int, _ num2 :Int) -> Int {
            return num1 * num2
        }
        var result3 = calculate(20, 20)
 
    • 默认参数:某些情况,如果没有传入具体参数,可以使用默认参数
      • func makecoffee(type :String = "卡布奇诺") -> String {
            return "制作一杯(type)咖啡。"
        }
        print(makecoffee("拿铁"))
        print(makecoffee())
        制作一杯拿铁咖啡。
        制作一杯卡布奇诺咖啡。
 
    • 可变参数:函数的参数个数可以不确定,但必须是相同类型,在参数类型名后面加入(…)来指示这是可变参数
      • func sum(numbers:Double...) -> Double {
            var total: Double = 0
            for number in numbers {
                total += number
            }
            return total
        }

        sum(100.0, 20, 30)
        sum(30, 80)
 
    • 引用类型(指针传递): 默认情况函数的参数是值传递,如果想改变外面的变量,则需要传递变量的地址,swift 提供 inout关键字就可以实现。注意:必须是变量
      • // 函数一:值传递
        func swap(var a : Int, var b : Int) {
            let temp = a;
            a = b;
            b = temp  
            print("a:(a), b:(b)")
        }

        var a = 10
        var b = 20
        swap(a, b: b)
        print("a:(a), b:(b)")
        a:20, b:10
        a:10, b:20

        // 函数二:指针的传递
        func swap2(inout m : Int, inout n : Int) {
            let temp = m
            m = n
            n = temp
            print("m:(m), n:(b)")
        }
        var m = 10
        var n = 20
        swap2(&m, n: &n)
        print("m:(m), n:(n)")
        m:20, n:20
        m:20, n:10
 
    • 嵌套函数:swift中可以嵌套函数,但是不推荐使用
      • let value = 55
        func test() {
            func demo() {
                print("value (value)")
            }
            print("test")
            demo()
        }

        //demo() // 错误
        test()
        test
        value 55
 
类的构造函数
  • 构造函数:
    • 构造函数类似于OC中的初始化方法:init方法
    • 默认情况下创建一个类时,必然会调用一个构造函数,如果没有编写任何构造函数,编译器也会提供一个默认的构造函数。
    • 如果是继承自NSObject,可以对父类的构造函数进行重写
 
  • 构造函数的基本使用
  • 1、类的属性必须有值,如果不是在定义时初始化值,可以在构造函数中赋值
      • class Student1: NSObject {
            var name : String
            var age : Int
           
            // 重写了NSObject(父类)的构造方法
            override init() {
                name = ""
                age = 0
            }
        }

        // 创建一个Student1对象
        let student1 = Student1()
         
 
  • 2、初始化时给属性赋值
    • 我们经常在创建对象是就给属性赋值,可以自定义构造函数
    • 注意:自定义了构造函数会覆盖init()方法,也就不再有默认的构造函数
      • class Student2: NSObject {
            var name : String
            var age : Int
            // 自定义构造函数,会覆盖init()函数
            init(name : String, age : Int) {
                self.name = name
                self.age = age
            }
        }
        // 创建一个Student2对象
        let student2 = Student2(name: "why", age: 18)
 
  • 3、字典转模型(初始化时传入字典)
    • 创建对象时,更多的是将字典转成模型
    • 注意:从字典中取出的是NSObject,任意类型,可以通过 as! 转成需要的类型再赋值(不可以直接赋值)
      • class Student3: NSObject {
            var name : String
            var age : Int
            // 自定义构造函数,会覆盖init()函数
            init(dict : [String : NSObject]) {
                name = dict["name"] as! String
                age = dict["age"] as! Int
            }
        }

        // 创建一个student3对象
        let dict = ["name" : "Siri", "age" : 18]
        let student3 = Student3(dict: dict)
        student3.name  // "Siri"
 
  • 4、字典转模型(利用KVC转化)
    • 利用KVC字典转模型会更加方便
    • 注意:KVC并不能保证会给所有的属性赋值,因此属性必须要有默认值
      • 基本数据类型默认值设置为0
      • 对象或者结构体类型定义为可选类型即可(可选类型没有赋值前为nil)
      • class Student4: NSObject {
            // 结构体或者类的类型,必须是可选类型.因为不能保证一定会赋值
            var name : String?
            // 基本数据类型不能是可选类型,否则KVC无法转化
            var age : Int = 0
            var address : String?
            // 自定义构造函数,会覆盖init()函数
            init(dict : [String : NSObject]) {
                // 必须先初始化对象
                super.init()
                // 调用对象的KVC方法字典转模型
                setValuesForKeysWithDictionary(dict)
            }
        }
        // 创建一个student4对象
        let dict4 = ["name" : "why", "age" : 18]
        let student4 = Student4(dict: dict)
         
                              
 
类的定义
  • 类的定义,可以没有父类,那么该类是rootClass
    • class 类名 : SuperClass {
          // 定义属性和方法
      }
 
类的属性
  • swift中类的属性有三种
    • 存储属性:存储实例的常量和变量
    • 计算属性:通过某种方式计算出来的属性
    • 类属性:与整个类自身相关的属性
 
  • 存储属性
    • class Person {   // 这种定义属性必须写初始值,因为系统不会自动初始化初始值,可选类型除外
         
          var age:Int = 1   // var 关键字修饰变量
         
          let life = 1      // let 修饰常量,不能修改
         
          var name: String?
         
      }

      var person = Person()

      person.age = 20          // 直接通过点运算符读写

      person.name = "Siri"

      print("person的名字是(person.name), person的生命是(person.life), person的年龄是(person.age)")
 
  • 计算属性
    • 并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性
    • 存储属性一般只提供getter方法
    • 如果只提供getter,而不提供setter,则该计算属性为只读属性,并且可以省略get{}
      • //  注意:计算属性的值是不固定的,只能声明为变量,不能使用let
        class Square {
            var Double = 0   // 边长
            var girth: Double {     // 周长 
                get {  
                    returnwidth * 4 
                    }
                set {               // 默认有一个newValue 的值 
                    width = newValue / 4
                    }
                }
            }
        var square = Square()
        square.width = 10
        print(square.girth)   // 调用 girth 属性的 get,输出结果是40
        square.girth = 200
        print(square.width)   // 调用 girth 属性的 set,并且把200传递给 newValue,输出结果是 50
      • // 注意:一个属性不能既是存储属性有事计算属性
        // 只读计算属性:只有get方法,没有set方法
        class Square3 {  
            var girth: Double {   // 周长 
                get {  
                    return40  
                }
            }
        }

        //也可以简写成:
        class Square4 {
            var girth: Double {   // 周长 
                return40
            }
        }
 
 
  • 类属性
    • 所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
    • 类属性的设置和修改,需要通过类来完成
      • // 类型属性:用类来访问的属性,用class关键字修饰的属性,也可以称为“类属性” 。
        // 特点:一个类只会有一份,类的多个实例对象都共享这唯一的一份。
        // 使用:类型属性不依赖于对象而存在,用类名来访问。
        // 注意:class修饰的类型属性只能是计算属性,不能是存储属性。
        class Circle {
            classvar PI: Double {// 所有用到的PI的值都是一样的,可以写成类属性
                return3.14  
            }
        }
        print("圆周率 = (Circle.PI)")
 
 
  • 属性监视器
    • 可以监视属性值的修改过程。需要在属性值被修改的时候做出响应的情况可以用属性监视器。计算属性可以在set方法中监听 ,而存储属性没有set,可以为存储属性添加willSet和didSet两个属性监视器。
      • // 属性监视器
        //可以监视属性值的修改过程。需要在属性值被修改的时候做出响应的情况可以用属性监视器。计算属性可以在set方法中监听,而存储属性没有set,可以为存储属性添加willSet和didSet两个属性监视器。
        class Square5 {
            var Double = 0.0 {
                 willSet {// willSet 有 newValue
                     print("willSet---new=(newValue), current=(width)")
                 }
                 didSet {// oldSet 有 oldValue 
                     print("didSet---old=(oldValue), current=(width)")
                 }
             }
         }
      • var square5 = Square5()
        square5.width = 10.0
        willSet---new=10.0, current=0.0
        didSet---old=0.0, current=10.0
 
      • //注意:willSet和didSet在属性初始化过程中不会被调用,只会当属性的值在初始化之外的地方被设置时被调用。也就是在声明时不会引发willSet和didSet的调用
        //如果在didSet方法中修改了属性的值,就不会再引发didSet的调用,也就不会循环引用。
        class Square6 {
            var Double = 0.0 {
                willSet {
                }
                didSet {
                    width = 80
                }
            }
        }

        var square6 = Square6()
        square6.width = 40
        print("width=(square6.width)")  // 打印:width=80.0
 
 
延迟属性
  • 第一次使用时才进行初始化的属性(相当于懒加载),使用关键字 @lazy 来标识一个延时属性。
  • 好处:让某些资源用到时再去加载,避免不必要的资源浪费。
  • 注意:延迟存储属性必须是变量,不能是常量。
    • class Dog {
          var name: String = "timo"
          init() {
              print("你是一条狗")
          }
      }
      class Person1 {   
          var dog: Dog = Dog() 
      }
      class LazyPerson {
          lazyvar dog: Dog = Dog()
      }
      var person1 = Person1() // 会直接打印  你是一条狗
      var lazyPerson = LazyPerson()     // 不会直接打印lazyPerson.dog// 调用才会打印
 
 
 
原文地址:https://www.cnblogs.com/10-19-92/p/5598510.html