笔记信息的来源大部分来自课程随堂的Keynote,以及一些我个人的看法,因为没有软件开发的基础,难免容易混淆一些基础概念,还请各位看官斧正。
这节课主要介绍了在 iOS 开发中经常使用的结构类型,呈现了一些 Swift 语言的一些基础特性,更详细的语法和特性,还是需要仔细阅读苹果官方的The Swift Programming Language来了解的。

基本数据类型

enum

在 Swift中:类、结构体、 和枚举都可以定义属性 及方法。类相比结构体仅仅多了可被继承的特性,而 enum 不能够拥有存储属性,只可以使用计算属性
enum 比较特别,在 Swift 中会经常被使用,当你需要声明一些东西,例如某个对象的多个不同状态,这些状态在不同的时候有不同的值,但一般不会同时拥有两个状态时候,比较适合使用 enum 来描述数据结构。
比如用来描述网络请求状态的时候,可以定义一个enum:

1
//TODO:

Optional

在 Swift 中 optional是由 enum 实现的,我们可以试想一下其内部结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum Optional <T> {
case None
case some(T
}
//它是一个泛型,T 表示 optional所关联值的类型,如果 Optional不是Nil,那T就是它的类型。
let x: String? = nil
...is...
let x = Optional
let x: String? = "Hello"
...is...
let x = Optional <String>.some("Hello")
var y = x!
switch x {
case some(let value): y = value
case None: // raise an exception
}

Array

数组是结构体,常用的方法如下:

1
2
3
4
5
6
7
8
9
10
var a = Array<String>()
is the same as
var a = [String]()
let animals = [“Giraffe”, “Cow”, “Doggie”, “Bird”]
animals.append(“Ostrich”) // won’t compile, animals is immutable (because of let)
let animal = animals[5] // crash (array index out of bounds)
// enumerating an Array
for animal in animals {
println(“\(animal)”)
}

Dictionary

字典在Swift中和数组一样,属于结构体。

1
2
3
4
5
6
7
8
9
var pac10teamRankings = Dictionary<String, Int>()
… is the same as …
var pac10teamRankings = [String:Int]()
pac10teamRankings = [”Stanford”:1, ”Cal”:10]
let ranking = pac10teamRankings[“Ohio State”] // ranking is an Int? (would be nil)
// use a tuple with for-in to enumerate a Dictionary
for (key, value) in pac10teamRankings {
println(“\(key) = \(value)”)
}

属性—Properties

  • 计算型属性-Computed Properties
    在结构体,类,和枚举中都可以使用计算型属性,而存储型属性不能应用在枚举中。
    某个属性在 set 和 get 的时候分别返回不同类型的参数的时候可以应用,或者在 set 或 get 的时候需要对参数进行加工时可以使用。
    set 方法中包含一个隐藏参数newValue, 例如,displayValue = 5, 5就是 newValue
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var displayValue: Double {
    get {
    return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
    }
    set {
    display.text = "\(newValue)"
    userIsInTheMiddleOfTypingANumber = false
    }
    }

从上面代码看set方法并没有为displayValue本身赋值,只是使用了其中的newValue为其他属性进行计算并赋值。

  • 属性观察 Property Observers
    属性观察会在iOS开发中大量应用,你可以通过willset 和 didset 观察 Property 的变化。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    这是一个直接的存储属性
    */
    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 }
    }

willSetdidSet会在属性被设置值期间自动调用,你可以在两种情况下应用属性观察,一种情况是你在自己的类中拥有一个存储属性,当其他方法设置它的值时,你想获得一个notice,然后根据这歌notice做一些事情。另一种情况是你继承了某些类,你并不需要对类中的 property 做什么修改,但它们被改变的时候你想知道,所以你可以在某些继承的类上重写父类的 willSet 和 didSet 。
在 iOS 开发中,我们用属性观察最多的地方就是更新界面UI, 比如你有一个viewcontroller,其中有一个view的property,可以在didset中进行view的重新绘制。

  • 惰性初始化 lazy initialization
    被标记 lazy 的 property 只有在被时候的时候才会初始化,你也可以在初始化的时候使用闭包(也就是在后面放一对括号)它会通过这个闭包来初始化自己。你甚至可以调用一个方法来初始化惰性属性,如果是普通的 property,在类初始化之前,类的方法都是不可用的。但在惰性属性中,直到有人试图去 get 这个惰性属性,它就被初始化了。我们对于惰性属性声明只能使用var,不能使用let.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    如果CalculatorBrain需要消耗大量系统资源,可以使用lazy声明。
    */
    lazy var brain=CalculatorBrain()
    /**
    使用闭包声明惰性属性。
    */
    lazy var someProperty: Type = { //constructthevalueofsomePropertyhere
    return<theconstructedvalue>
    }()
    lazyvarmyProperty=self.initializeMyProperty

初始化

##Initialization
讨论初始话我们先弄明白第一个问题:我们在什么情况下需要实现 init方法呢?事实上大多数时候并不需要init方法,因为类或者结构体里边大部分的常量和变量都会通过赋值被初始化,或者有些属性是 Optional 的,这样即使它们是nil也没有关系,就像 StoryBoard 里的 OutLet 一样,又或者可以用闭包来初始化,你也可以使用 lazy 机制,从而避免使用 init 方法。

但如果你确实需要一个 init 方法,我们来了解一下在默认的初始化方法是如何产生的。

  • 第一种情况就是如果一个基类class基类指的是没有父类的类,它所有的属性都有默认值,那么它就会自动得到一个 没有参数 的 init 方法。

    1
    2
    3
    4
    /**
    ClalculatorBarin() 后面的括弧就是默认没有参数的init方法
    */
    let brain = ClalculatorBarin()
  • 如果是一个结构体struct没有自定义初始化方法,它会默认得到一个包括 所有属性和参数init方法, 并且所有的属性和参数都比配

    1
    2
    3
    4
    5
    struct MyStruct {
    var x: Int = 42
    var 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