美文网首页
Swift 属性

Swift 属性

作者: 小猪蛋蛋 | 来源:发表于2020-07-06 10:38 被阅读0次

    swift中跟实例相关的属性可以分为两大类:

    * 存储属性

    • 类似于成员变量这个概念
    • 存储在实例的内存中
    • 结构体、类可以定义存储属性
    • 枚举不可以定义存储属性
      关于枚举为什么不能定义存储属性:\color{red}{枚举的内存只存储枚举的case或关联属性值}
    enum textEnum{
        case text1,text2
    }
    var p = textEnum.text1
    //内存中会拿出一个字节存储 p
    enum textEnum1{
        case text1(Int),text2(Double)
    }
    var p1 = textEnum1.text1(20)
    //枚举内存中会有8个字节存储关联属性
    enum textEnum2: Int{
        var x: Int //错误的
        case text1 = 10,text2 = 20
    }
    var p2 = textEnum2.text1
    //内存中会拿出一个字节存储 p2,当你在枚举中写道 var x: Int ,貌似是顶一个一个存储属性,但是不会将 var x: Int的内存放到枚举中
    
    在创建类 或 结构体的实例时,必须为所有的存储属性设置一个合适的初始值
    • 可以在初始化器里为存储属性设置一个初始值
    • 可以分配一个默认的属性值作为属性定义的一部分

    * 计算属性

    • 本质就是方法(函数)
    • 计算属性的特点是不占用实例的内存
    • 枚举、结构体、类都可以定义计算属性

    set传入的新值默认叫做newValue,也可以自定义,例如定义为:newDiameter

    struct Circle {
       var radius: Double
       var diameter: Double {
           set(newDiameter) {
               radius = newDiameter / 2
           }
         //set不写()的话,默认为newValue
         //set{
          //     radius = newValue / 2
          // }  
           get {
             radius * 2 }
           }
    }
    

    只读计算属性:只有get,没有set

    struct Circle {
        var radius: Double
        var diameter: Double {
            get {
                radius * 2
            } 
        }
    }
    

    \color{red}{注意:如果写个set,则必须要有get;反之,只有get,则为只读属性}

    延迟存储属性(Lazy Stored Property)

    使用lazy可以定义一个延迟存储属性,在第一次用到属性的时候才会进行初始化

    class Car {
        init() {
            print("Car init!")
        }
        func run() {
            print("Car is running!")
        }
    }
    class Person {
        lazy var car = Car()
        init() {
            print("Person init!")
        }
        func goOut() { 
            car.run()
        }
    }
    let p = Person()
    print("--------")
    p.goOut()
    

    打印结果为:

    Person init!
    --------
    Car init!
    

    当在Person中定义car的时候,前面加 lazy,表明car为延迟属性,当let p = Person()的时候,不会对car进行初始化操作,但是当p.goOut()的时候,goOut()方法中用到了Car,此时对car进行了初始化操作。

    应用实例:

    class PhotoView {
        lazy var image: Image = {
            let url = "https://www.520it.com/xx.png"
            let data = Data(url: url)
            return Image(data: data)
        }()
    }
    var photo = PhotoView()
    photo.image
    

    \color{red}{注意:}

    • lazy属性必须是var,不能是let(let必须在实例的初始化方法完成之前就拥有值)
    • 如果多条线程同时第一次访问lazy属性 ,无法保证属性只被初始化1次
    • 当结构体包含一个延迟存储属性时,只有var才能访问延迟存储属性 ,因为延迟属性初始化时需要改变结构体的内存
      例如:


      image.png

    属性观察器(Property Observer)

    可以为 \color{red}{非lazy的var存储属性} 设置属性观察器,不能为计算属性添加属性观察器

    struct Circle {
        var radius: Double {
            //属性的值将要改变,newValue是将要改变的值
            willSet {
                print("willSet", newValue)
            }
            //属性的值已经改变,oldValue是改变之前的值
            didSet {
                print("didSet", oldValue, radius)
            }
        }
        init() {
            self.radius = 1.0
            print("Circle init!")
        }
    }
    // Circle init!
    var circle = Circle()
    // willSet 10.5
    // didSet 1.0 10.5 
    circle.radius = 10.5
    // 10.5
    print(circle.radius)
    
    • willSet会传递新值,默认叫newValue
    • didSet会传递旧值,默认叫oldValue
    • 在初始化器中设置属性值不会触发willSet和didSet ,在属性定义时设置初始值也不会触发willSet和didSet

    \color{red}{属性观察器、计算属性的功能,同样可以应用在全局变量、局部变量身上}

    如果有什么不对的地方,欢迎指正,大家共同进步!

    相关文章

      网友评论

          本文标题:Swift 属性

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