Swift学习笔记(二)

String

Swift 的String和Character类型提供了一个快速的,兼容 Unicode 的方式来处理代码中的文本信息。 创建和操作字符串的语法与 C 语言中字符串操作相似,轻量并且易读。 字符串连接操作只需要简单地通过+号将两个字符串相连即可。 与 Swift 中其他值一样,能否更改字符串的值,取决于其被定义为常量还是变量。

定义

定义一个变量,它的类型是String,值为“xayoung”

1
var CoderX = "xayoung"

字符串可变性 (String Mutability)

1
2
CoderX += "is a coder!"
//CoderX现在为"xayoung is a coder"

可变性中与OC的不同点

在 Objective-C 和 Cocoa 中,您通过选择两个不同的类(NSString和NSMutableString)来指定该字符串是否可以被修改,Swift 中的字符串是否可以修改仅通过定义的是变量还是常量来决定,实现了多种类型可变性操作的统一。

其他不同点

String 和 NSString 有着良好的互相转换的特性,但是现在 Cocoa 所有的 API 都接受和返回 String 类型。但Swift 中 String 是 struct,相比起 NSObject 的 NSString 类来说,更切合字符串的 “不变” 这一特性。通过配合常量赋值 (let) ,这种不变性在多线程编程时就非常重要了,它从原理上将程序员从内存访问和操作顺序的担忧中解放出来。另外,在不触及 NSString 特有操作和动态特性的时候,使用 String 的方法,在性能上也会有所提升。

String特有的一些特性

1
2
3
4
let Coder = "xayoung"
for i in Coder.characters {
print(i)
}


枚举

在 Swift 中,枚举类型是一等(first-class)类型。它们采用了很多传统上只被类(class)所支持的特征,例如计算型属性(computed properties),用于提供关于枚举当前值的附加信息, 实例方法(instance methods),用于提供和枚举所代表的值相关联的功能。枚举也可以定义构造函数(initializers)来提供一个初始成员值;可以在原始的实现基础上扩展它们的功能;可以遵守协议(protocols)来提供标准的功能。

定义

1
2
3
enum Eye { 
case Left, Right
}

不像 C 和 Objective-C 一样,Swift 的枚举成员在被创建时不会被赋予一个默认的整数值。在上面的CompassPoints例子中,North,South,East和West不是隐式的等于0,1,2和3。相反的,这些不同的枚举成员在CompassPoint的一种显示定义中拥有各自不同的值。

匹配枚举值和Switch语句

1
2
3
4
5
var whichEye = Eye.Left
switch whichEye {
case .Left: eyeCenter.x -= eyeHorizontalSeparation / 2
case .Right: eyeCenter.x += eyeHorizontalSeparation / 2
}

如在控制流(Control Flow)中介绍,当考虑一个枚举的成员们时,一个switch语句必须全面。如果忽略了.West这种情况,上面那段代码将无法通过编译,因为它没有考虑到CompassPoint的全部成员。全面性的要求确保了枚举成员不会被意外遗漏。
当不需要匹配每个枚举成员的时候,你可以提供一个默认default分支来涵盖所有未明确被提出的任何成员


类和结构体

类和结构体对比

Swift 中类和结构体有很多共同点。共同处在于:

  • 定义属性用于存储值
  • 定义方法用于提供功能
  • 定义附属脚本用于访问值
  • 定义构造器用于生成初始化值
  • 通过扩展以增加默认实现的功能
  • 符合协议以对某类提供标准功能

与结构体相比,类还有如下的附加功能:

  • 继承允许一个类继承另一个类的特征
  • 类型转换允许在运行时检查和解释一个类实例的类型
  • 解构器允许一个类实例释放任何其所被分配的资源
  • 引用计数允许对一个类的多次引用

定义

1
2
3
4
5
6
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}

上边定义了一个名为VideoMode的类,用来描述一个视频显示器的特定模式。这个类包含了四个储存属性变量。第一个是分辨率,它被初始化为一个新的Resolution结构体的实例,具有Resolution的属性类型。新VideoMode实例同时还会初始化其它三个属性,它们分别是,初始值为false(意为“non-interlaced video”)的interlaced,回放帧率初始值为0.0的frameRate和值为可选String的name。name属性会被自动赋予一个默认值nil,意为“没有name值”,因为它是一个可选类型。

1
2
3
4
5
6
7
8
struct Scaling {
let FaceRadiusToEyeRadiusRatio: CGFloat = 10
let FaceRadiusToEyeOffsetRatio: CGFloat = 3
let FaceRadiusToEyeSeparationRatio: CGFloat = 1.5
let FaceRadiusToMouthWidthRatio: CGFloat = 1
let FaceRadiusToMouthHeightRatio: CGFloat = 3
let FaceRadiusToMouthOffsetRatio: CGFloat = 3
}

属性访问

通过使用点语法(dot syntax),你可以访问实例中所含有的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(.)连接

1
let mouthWidth = faceRadius / Scaling.FaceRadiusToMouthWidthRatio

也可以使用点语法为属性变量赋值:

1
Scaling.FaceRadiusToMouthWidthRatio = 50.0

与 Objective-C 语言不同的是,Swift 允许直接设置结构体属性的子属性。上面的最后一个例子,就是直接设置了someVideoMode中resolution属性的width这个子属性,以上操作并不需要重新设置resolution属性。

注意点

在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Booleans)、字符串(string)、数组(array)和字典(dictionaries),都是值类型,并且都是以结构体的形式在后台所实现。
在 Swift 中,所有的结构体和枚举都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。
而类是引用类型,与值类型不同,引用类型在被赋予到一个变量、常量或者被传递到一个函数时,操作的是引用,其并不是拷贝。因此,引用的是已存在的实例本身而不是其拷贝。


协议

协议(Protocol)用于定义完成某项任务或功能所必须的方法和属性,协议实际上并不提供这些功能或任务的具体实现(Implementation)–而只用来描述这些实现应该是什么样的。类,结构体,枚举通过提供协议所要求的方法,属性的具体实现来采用(adopt)协议。任意能够满足协议要求的类型被称为协议的遵循者。

代理模式

1
2
3
4
//声明datasource协议,这里需要把FaceVireDataSource变成一个类才能实现的协议,
protocol FaceViewDataSource: class {
func smilinessForFaceView(sender: FaceView) -> Double?
}

实现代理方法

1
2
//使用操作符??,左侧有值使用它的值,左侧为nil时则使用右侧
let smiliness = dataSource?.smilinessForFaceView(self) ?? 0.0

1
2
3
4
5
6
7
8
9
10
class HappinessViewController: UIViewController, FaceViewDataSource {

//设置datasource代理
@IBOutlet weak var faceView: FaceView! {
didSet {
faceView.dataSource = self
faceView.addGestureRecognizer(UIPinchGestureRecognizer(target: faceView, action: "scale:"))

}
}

其他

最后展示截止到课时6,最新的demo效果图。附上代码的github连接:https://github.com/xayoung/CS193P-DemoCode
此处输入图片的描述