当前位置: 首页 > 编程学习 > 其它语言 > Swift > 正文

Swift4 属性,例子代码

2018-04-22 来源:博客园/CC_Joy

属性

苹果官方文档 Properties

苹果官方文档翻译 属性

属性可以将值与特定的类、结构体或者是枚举联系起来。

存储属性

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8

常量结构体实例的储存属性

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property

延迟储存属性

延迟存储属性的初始值在其第一次使用时才进行计算。声明前标注 lazy 修饰语来表示一个延迟存储属性。且声明必须为变量。

class DataImporter {
    
    //DataImporter is a class to import data from an external file.
    //The class is assumed to take a non-trivial amount of time to initialize.
    
    var fileName = "data.txt"
    // the DataImporter class would provide data importing functionality here
}
 
class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
    // the DataManager class would provide data management functionality here
}
 
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property has not yet been created
print(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// prints "data.txt"

储存属性与实例变量

Swift 属性没有与之相对应的实例变量,并且属性的后备存储不能被直接访问。

计算属性

image

struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
    size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// prints "square.origin is now at (10.0, 10.0)"

简写设置器(setter)声明

如果一个计算属性的设置器没有为将要被设置的值定义一个名字,那么他将被默认命名为 newValue 。

struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

只读计算属性

一个有读取器但是没有设置器的计算属性就是所谓的只读计算属性。

去掉 get 关键字和他的大扩号来简化只读计算属性的声明:

struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// prints "the volume of fourByFiveByTwo is 40.0"

属性观察者

属性观察者会观察并对属性值的变化做出回应。

  • willSet 会在该值被存储之前被调用。
  • didSet 会在一个新值被存储后被调用。
    class StepCounter {
        var totalSteps: Int = 0 {
            willSet(newTotalSteps) {
                print("About to set totalSteps to \(newTotalSteps)")
            }
            didSet {
                if totalSteps > oldValue  {
                    print("Added \(totalSteps - oldValue) steps")
                }
            }
        }
    }
    let stepCounter = StepCounter()
    stepCounter.totalSteps = 200
    // About to set totalSteps to 200
    // Added 200 steps
    stepCounter.totalSteps = 360
    // About to set totalSteps to 360
    // Added 160 steps
    stepCounter.totalSteps = 896
    // About to set totalSteps to 896
    // Added 536 steps

    全局变量和局部变量

    计算属性和观察属性的能力同样对全局变量和局部变量有效。

    类型属性

    可以定义属于类型本身的属性,不是这个类型的某一个实例的属性。这个属性只有一个拷贝,无论你创建了多少个类对应的实例。这样的属性叫做类型属性。
    详细参考文档介绍。

    类型属性语法

    static 关键字来开一类型属性

    struct SomeStructure {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 1
        }
    }
    enum SomeEnumeration {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 6
        }
    }
    class SomeClass {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 27
        }
        class var overrideableComputedTypeProperty: Int {
            return 107
        }
    }

    查询和设置类型属性

    类型属性在类里查询和设置,而不是这个类型的实例。

    print(SomeStructure.storedTypeProperty)
    // prints "Some value."
    SomeStructure.storedTypeProperty = "Another value."
    print(SomeStructure.storedTypeProperty)
    // prints "Another value."
    print(SomeEnumeration.computedTypeProperty)
    // prints "6"
    print(SomeClass.computedTypeProperty)
    // prints "27"

    接下来的例子使用了两个存储类型属性作为建模一个为数字音频信道音频测量表的结构体的一部分。每一个频道都有一个介于 0 到 10 之间的数字音频等级。

    下边的图例展示了这个音频频道如何组合建模一个立体声音频测量表。当频道的音频电平为 0,那个对应频道的灯就不会亮。当电平是 10 ,所有这个频道的灯都会亮。在这个图例里,左声道当前电平是 9 ,右声道的当前电平是 7 :

    image

    struct AudioChannel {
        static let thresholdLevel = 10
        static var maxInputLevelForAllChannels = 0
        var currentLevel: Int = 0 {
            didSet {
                if currentLevel > AudioChannel.thresholdLevel {
                    // cap the new audio level to the threshold level
                    currentLevel = AudioChannel.thresholdLevel
                }
                if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                    // store this as the new overall maximum input level
                    AudioChannel.maxInputLevelForAllChannels = currentLevel
                }
            }
        }
    }
     
    var leftChannel = AudioChannel()
    var rightChannel = AudioChannel()
     
    leftChannel.currentLevel = 7
    print(leftChannel.currentLevel)
    // prints "7"
    print(AudioChannel.maxInputLevelForAllChannels)
    // prints "7"
     
    rightChannel.currentLevel = 11
    print(rightChannel.currentLevel)
    // prints "10"
    print(AudioChannel.maxInputLevelForAllChannels)
    // prints "10"