CS193P 第四课笔记
笔记信息的来源大部分来自课程随堂的Keynote,以及一些我个人的看法,因为没有软件开发的基础,难免容易混淆一些基础概念,还请各位看官斧正。
这节课主要介绍了在 iOS 开发中经常使用的结构类型,呈现了一些 Swift 语言的一些基础特性,更详细的语法和特性,还是需要仔细阅读苹果官方的The Swift Programming Language
来了解的。
基本数据类型
enum
在 Swift中:类、结构体、 和枚举都可以定义属性 及方法。类相比结构体仅仅多了可被继承的特性,而 enum 不能够拥有存储属性
,只可以使用计算属性
。
enum 比较特别,在 Swift 中会经常被使用,当你需要声明一些东西,例如某个对象的多个不同状态,这些状态在不同的时候有不同的值,但一般不会同时拥有两个状态时候,比较适合使用 enum 来描述数据结构。
比如用来描述网络请求状态的时候,可以定义一个enum:
Optional
在 Swift 中 optional
是由 enum
实现的,我们可以试想一下其内部结构。
Array
数组是结构体,常用的方法如下:
Dictionary
字典在Swift中和数组一样,属于结构体。
属性—Properties
- 计算型属性-Computed Properties
在结构体,类,和枚举中都可以使用计算型属性,而存储型属性不能应用在枚举中。
某个属性在 set 和 get 的时候分别返回不同类型的参数的时候可以应用,或者在 set 或 get 的时候需要对参数进行加工时可以使用。
set 方法中包含一个隐藏参数newValue
, 例如,displayValue = 5, 5就是 newValue123456789var displayValue: Double {get {return NSNumberFormatter().numberFromString(display.text!)!.doubleValue}set {display.text = "\(newValue)"userIsInTheMiddleOfTypingANumber = false}}
从上面代码看set方法并没有为displayValue本身赋值,只是使用了其中的newValue为其他属性进行计算并赋值。
- 属性观察 Property Observers
属性观察会在iOS开发中大量应用,你可以通过willset 和 didset 观察 Property 的变化。1234567891011/**这是一个直接的存储属性*/var someStoredProperty: Int = 42 {willSet { newValue is the new value }didSet { oldValue is the old value }}override var inheritedProperty {willSet { newValue is the new value }didSet { oldValue is the old value }}
willSet
和didSet
会在属性被设置值期间自动调用,你可以在两种情况下应用属性观察,一种情况是你在自己的类中拥有一个存储属性,当其他方法设置它的值时,你想获得一个notice,然后根据这歌notice做一些事情。另一种情况是你继承了某些类,你并不需要对类中的 property 做什么修改,但它们被改变的时候你想知道,所以你可以在某些继承的类上重写父类的 willSet 和 didSet 。
在 iOS 开发中,我们用属性观察最多的地方就是更新界面UI, 比如你有一个viewcontroller,其中有一个view的property,可以在didset中进行view的重新绘制。
- 惰性初始化 lazy initialization
被标记 lazy 的 property 只有在被时候的时候才会初始化,你也可以在初始化的时候使用闭包(也就是在后面放一对括号)它会通过这个闭包来初始化自己。你甚至可以调用一个方法来初始化惰性属性,如果是普通的 property,在类初始化之前,类的方法都是不可用的。但在惰性属性中,直到有人试图去 get 这个惰性属性,它就被初始化了。我们对于惰性属性声明只能使用var
,不能使用let
.1234567891011/**如果CalculatorBrain需要消耗大量系统资源,可以使用lazy声明。*/lazy var brain=CalculatorBrain()/**使用闭包声明惰性属性。*/lazy var someProperty: Type = { //constructthevalueofsomePropertyherereturn<theconstructedvalue>}()lazyvarmyProperty=self.initializeMyProperty
初始化
##Initialization
讨论初始话我们先弄明白第一个问题:我们在什么情况下需要实现 init
方法呢?事实上大多数时候并不需要init方法,因为类或者结构体里边大部分的常量和变量都会通过赋值被初始化,或者有些属性是 Optional 的,这样即使它们是nil也没有关系,就像 StoryBoard 里的 OutLet 一样,又或者可以用闭包来初始化,你也可以使用 lazy 机制,从而避免使用 init 方法。
但如果你确实需要一个 init 方法,我们来了解一下在默认的初始化方法是如何产生的。
第一种情况就是如果一个基类
class
,基类指的是没有父类的类,它所有的属性都有默认值,那么它就会自动得到一个 没有参数 的 init 方法。1234/**ClalculatorBarin() 后面的括弧就是默认没有参数的init方法*/let brain = ClalculatorBarin()如果是一个结构体
struct
没有自定义初始化方法,它会默认得到一个包括 所有属性和参数 的init
方法, 并且所有的属性和参数都比配12345struct MyStruct {var x: Int = 42var y: String = "moltuae"init(x: Int, y: String) // comes for free你可以在 init 方法中做什么?
你可以在里面设置任何 property 的值,你甚至可以给property 设置默认值,即使你把它设置为等于12,在你的init里,你可以把一些东西重置为别的什么。
你可以给常量 property 赋值let
在你的类或者结构体里尼可以调用其他的init方法,使用self .init
你可以调用有不同参数的其它init方法
当然,在类中你也可以调用super.init,调用父类的初始化方法。
当时调用其它的init方法有很多规则,尤其是在 类 里,在结构体中,这不是一个大问题。我们先来看看哪些事你必须要做的:
1.在你的类里,所有的property都必须初始化,它们都必须有值, optionals 的nil也是值
。
2 在类中,提供了两种类型的构造器来初始化,一种是 Convenience Init
另一种是 Designated Initializers
RxSwift