本文是学习《The Swift Programming Language》整理的相关随笔,基本的语法不作介绍,主要介绍Swift中的一些特性或者与OC差异点。
系列文章:
常量的结构体实例的属性(Stored Properties of Constant Structure Instances)
If you create an instance of a structure and assign that
instance to a constant, you cannot modify the instance’s
properties, even if they were declared as variable
properties:
- 常量的结构体实例的属性即使是
var
修饰也不能更改它的值
例子:
struct FixedLengthRange{
var firstValue:Int
let length:Int
}
let rangeOfFourItems = FixedLengthRange(firstValue:0,length:4)
rangeOfFourItems.firstValue = 6;
编译错误:
error: MyPlayground.playground:527:29: error: cannot assign to property: 'rangeOfFourItems' is a 'let' constant
rangeOfFourItems.firstValue = 6;
~~~~~~~~~~~~~~~~ ^
MyPlayground.playground:526:1: note: change 'let' to 'var' to make it mutable
let rangeOfFourItems = FixedLengthRange(firstValue:0,length:4)
^~~
原因:
Because rangeOfFourItems is declared as a constant (with
the let keyword), it is not possible to change its
firstValue property, even though firstValue is a variable
property.
This behavior is due to structures being value types. When
an instance of a value type is marked as a constant, so
are all of its properties.
- 如果一个结构体实例被
constant
修饰,它的所有属性也是默认的常量
延迟存储属性(Lazy Stored Properties)
A lazy stored property is a property whose initial value
is not calculated until the first time it is used. You
indicate a lazy stored property by writing the lazy
modifier before its declaration.
- 延迟存储属性只有当使用时才会被创建,用
lazy
关键字修饰
例子:
class DataImporter{
var filename = "data.txt"
}
class DataManager{
lazy var importer = DataImporter()
var data = [String]()
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
print(manager.importer.filename)
执行结果:
someVideoMode === otherVideoMode
someVideoMode !== thirdVideoMode
data.txt
计算属性(Computed Properties)
In addition to stored properties, classes, structures, and
enumerations can define computed properties, which do not
actually store a value. Instead, they provide a getter and
an optional setter to retrieve and set other properties
and values indirectly.
- 除了存储属性,类与结构体,枚举都可以定义计算属性,计算属性是一个可选的
setter
来间接设置其他属性或变量的值
例子:
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))")
执行结果:
square.origin is now at (10.0, 10.0)
便捷的Setter声明(Shorthand Setter Declaration)
If a computed property’s setter does not define a name for
the new value to be set, a default name of newValue is
used. Here’s an alternative version of the Rect structure,
which takes advantage of this shorthand notation:
- 如果一个计算属性的的set方法没有定义一个新的名字给这个新的值,那么默认的名字就是
newValue
例子:
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{
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
只读的计算属性(Read-Only Computed Properties)
A computed property with a getter but no setter is known
as a read-only computed property. A read-only computed
property always returns a value, and can be accessed
through dot syntax, but cannot be set to a different
value.
- 计算属性如果只写入了get方法没有set方法,那么就是只读的计算属性
例子:
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)")
例子:
the volume of fourByFiveByTwo is 40.0
属性观察器(Property Observers)
Property observers observe and respond to changes in a
property’s value. Property observers are called every
time a property’s value is set, even if the new value is
the same as the property’s current value.
You can add property observers to any stored properties
you define, except for lazy stored properties. You can
also add property observers to any inherited property
(whether stored or computed) by overriding the property
within a subclass. You don’t need to define property
observers for nonoverridden computed properties, because
you can observe and respond to changes to their value in
the computed property’s setter. Property overriding is
described in Overriding.
You have the option to define either or both of these
observers on a property:
- willSet is called just before the value is stored.
- didSet is called immediately after the new value is
stored.
- 当属性发生变化时会触发属性观察器,可以给除了延迟存储属性的属性添加观察器。同样子类继承的属性一样也可以添加观察器,只需要子类中重载属性即可。
-
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 = 10
stepCounter.totalSteps = 20
执行结果:
About to set totalSteps to 10
Added 10 steps
About to set totalSteps to 20
Added 10 steps
全局变量与局部变量(Global and Local Variables)
Global variables are variables that are defined outside of
any function, method, closure, or type context. Local
variables are variables that are defined within a function,
method, or closure context.
- 全局变量是在函数、方法、闭包或任何类型之外定义的变量,局部变量是在函数、方法或闭包内部定义的变量。
例子:
var globalNum = 0;
func changeNumToTen(){
var localNum = 10;
globalNum = 10;
print("globalNum:\(globalNum) localNum:\(localNum)");
}
changeNumToTen();
globalNum = 20;
print("globalNum:\(globalNum)");
执行结果:
globalNum:10 localNum:10
globalNum:20
类型属性(Type Properties)
Instance properties are properties that belong to an instance
of a particular type. Every time you create a new instance of
that type, it has its own set of property values, separate
from any other instance.
You can also define properties that belong to the type
itself, not to any one instance of that type. There will only
ever be one copy of these properties, no matter how many
instances of that type you create. These kinds of properties
are called type properties.
- 类型本身可以定义属性,不管有多少个实例,这些属性只有唯一一份
类型属性语法(Type Property Syntax)
You define type properties with the static keyword. For
computed type properties for class types, you can use the
class keyword instead to allow subclasses to override the
superclass’s implementation.
- 使用关键字
static
来定义类型属性,另外可以以使用关键字class
来定义计算类型属性,让子类可以重写该方法(使用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;
}
}
class SubSomeClass:SomeClass{
override class var overrideableComputedTypeProperty: Int {
return 108;
}
}
print(SomeStructure.storedTypeProperty)
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
print(SomeEnumeration.computedTypeProperty)
print(SomeClass.computedTypeProperty)
print(SomeClass.overrideableComputedTypeProperty)
print(SubSomeClass.overrideableComputedTypeProperty)
执行结果:
Some value.
Another value.
6
27
107
108