Developing iOS 8 Apps with Swift学习日记 ---- Class 4

swfit中的数据结构

  • class
  • struct
  • enum

Similarities

  • 声明语法很相似
    class Foo {}
    struct Foo {}
    enum op {}

  • 都能拥有 属性方法 ,enum本身不能存储任何值,只能将值存储在枚举的关联信息中

  • 结构体和类会有初始化构造器(Initializers)

Differences

  • 只有类可以继承
  • 也只有类具有内省和转型的性质(Introspection and casting)
  • 最重要的区别 值类型(strcut, enum) VS 引用类型(class)
    结构体和枚举的传递和存储时通过拷贝过的变量,而类属于引用类型,我们传递的是这些对象的指针,而这些对象本身存储在堆内存中(堆内存中的对象,系统会通过ARC自动为我们管理)

Methods

  • 重写一个父类函数需要使用 override

  • 在函数前面标记 final 表示这个函数将不能被重写

  • 每个函数都有internal name(函数内部使用的名字) 和 external name(函数外部使用的名字)
    func foo(external internal: Int) { let local = internal }
    func bar() { let result = foo(external: 123) }

  • 如果不想使用external name可以使用 _ ,表示 I don't care what is external name
    func foo(_ internal: Int) { let local = internal }
    func bar() { let result = foo(123) }

  • _ 一般是默认加在第一个参数上的, so
    func foo(internal: Int) { let local = internal }
    func bar() { let result = foo(123) }

  • 或者也可以强制第一个参数是必要的,通过 #
    func foo(#internal: Int) { let local = internal }
    func bar() { let result = foo(internal: 123) }

  • 除了第一个参数,我们一般是会给其他的参数命名,不管是通过外部命名或者内部命名
    func foo(first: Int, second: Double) { let local = first }
    func bar() { let result = foo(123, second: 5.5) }

Properties

Property Observers

  • willSet and didSet (通常用在改变UI,当Properties发生改变时,意味着UI也需要产生相应的更新)

Lazy Initialization

  • 只有在被用到的时候才会产生初始化
  • lazy var brain = CalculatorBrain()
  • 可以使用闭包进行初始化
  • lazy var someProperty: Type = { return }()
  • 可以使用函数进行初始化
  • lazy var myProperty = self.initializeMyProperty()
  • 依旧遵循所有属性必须初始化的规则
  • 只有var可以进行懒加载,let并不醒
  • 这个特性一般用来处理一些错综复杂的初始化依赖

Initialization

Free init

  • 一个基类(没有父类)里的所有Property都有赋值,那你就可以使用一个默认没有参数的 init 方法
  • 一个结构体当且仅当没有初始化函数时,它可以得到一个将所有Property作为参数的初始化方法

What can you do inside an init?

  • 给变量赋值
  • 给常量赋值
  • 调用其他init方法 self.init()
  • 调用 super.init()

What are you required to do inside init?

  • 所有Property必需赋值
  • 在Swfit的中里提供两种类型的构造器来初始化

Convenience Init

  • 只能调用本类的designated initializer
  • 它能通过调用其他的convenience initializer来间接调用designated initializer
  • 必需先直接或者间接调用designated initializer,才能访问其他的值
  • 其他初始化函数的调用,无论是convenience initializer调用designator initializer,还是designator initializer调用父类的designator initializer。
    所有这些都必需在你开始访问property和方法之前完成

Designated Init

  • 只能调用父类的designated initializer
  • 必需执行父类的初始化函数,才能给父类的Property赋值

继承初始化(Inheriting init)

  • 如果你没有在你的类中实现任何designated initializers,那么你将继承父类中的所有designated initializers,否则你将不能继承父类的任何一个designated initializers
    (要么就全部继承,要么就一个都不要)
  • 如果你重写了父类的所有designated initializers,那你就继承了父类的所有convenient initializers
  • 如果你一个初始化函数都没写,那将继承父类中全部初始化函数

Required init

  • 在初始化函数前面加上required
  • 它的子类必需实现这个方法

Failable init

  • 有些初始化函数允许失败并且返回nil
  • init?(arg1: Type1, ...) { //might return nil here }
  • 举个梨子
  • let image = UIImage(named: "foo") // image is an Optional UIImage
  • 所以我们经常使用 if let
  • if let image = UIImage(named: "foo") { } else { }

AnyObject

  • 指向一个对象的指针,也就是一个类的实例,只是你不知道它的类是什么
    var destinationViewController : AnyObject
  • 防止应用崩溃,使用
    if let calcVC = destinationViewController as? CalculatorViewController { ... }
  • 判断是否是对应类类型可以使用 is (比较少用)
    if destinationViewController is CalculatorViewController { ... }
  • [AnyObject] 数组
    var toolbarItems: [AnyObject]
    for item in toolbarItems { if let toolbarItem = item as? UIBarButtonItem { ...} }
  • 有一个更酷的方法
    for toolbarItem in toolbarItems as [UIBarButtonItem] { ... }
  • 另一个出现AnyObject的地方
    @IBAction func appendDigit(sender: AnyObject) { if let sendingButton = sender as? UIButton { let digit = sendingButton.currentTitle! } }
  • One more thing
    let button: AnyObject = UIButton.buttonWithType(UIButtonType.System)
    let title = (button as UIButton).currentTitle

Casting

  • 如果let vc: UIViewController = CalculatorViewController()
    我们不能使用 vc.enter(),因为enter是CalculatorViewController类的方法
    转换 if let calVC = vc as? CalculatorViewController { ... }

Function

Some Array Methods

  • += [T] //not += T
  • first -> T //optional
  • last -> T //optional

Basic

  • var a = [a,b,c]
  • append(T)
  • insert(T, atIndex: Int) //a.insert(d, atIndex:1), a = [a,d,b,c]
  • splice(Array, atIndex: Int) //a.splice([d,e], atIndex:1), a = [a,d,e,b,c] 在array中插入array
  • rmoveAtIndex(Int) //a.removeAtIndex(1). a = [b,c]
  • removeRange(Range) //a.removeRange(0..<2), a= [c]
  • replaceRange(Range, [T]) // a.replaceRange(0...1, with: [x,y,z]) , a = [x,y,z,b]
  • sort(isOderedBefore: (T, T) -> Bool) // 需要提供一个比较函数,通常使用闭包 e.g. a.sort { $0 < $1 }

More Cool

  • filter(includeElement: (T) -> Bool) -> [T] //过滤掉不想要的元素然后返回过滤后的Array
  • map(transform: (T) -> U) ->[U] //将原来Array中的每一个元素映射到一个新的Array
    let stringified: [String] = [1,2,3].map { "\($0)" } //将他们映射到字符串的形式
  • reduce(initial: U, combine: (U, T) -> U) -> U
    let sum: Int = [1,2,3].reduce(0) { $0 + $1 } // 将数组中的元素累加起来

String

String.Index

  • 字素是显示为单字符的文本单元,在Unicode中,一个字素有可能由多个字符组成,所以不能在一个字符串中像数组一样使用索引
    var s = "hello"
    let index = advance(s.startIndex, 2) //得到指向l的指针
    s.splice("abc", index) // s = "heabcllo"
    let startIndex = advance(s.startIndex, 1)
    let endIndex = advance(s.startIndex, 6)
    let substring = s[index..
  • rangeOfString
    let num = "56.25"
    if let decimalRange = num.rangeOfString(".") { let wholeNumberPart = num[num.startIndex..

Other Sring Methods

  • description -> string //Printable
  • endIndex -> String.Index
  • hasPrefix(String) -> Bool
  • hasSuffix(String) -> Bool
  • toInt() ->Int? // no toDoule

为什么没有toDouble,因为当你想要转换成Double时,你需要指定一些东西,你需要多少的有效位数?你需要小数点后几位?事实上没有地方去指定这些东西。如果有一个toDouble方法,那么会有一大堆的参数来指定转换中的细节

  • capitalizedString -> String
  • lowercaseString -> String
  • uppercaseString -> String
  • join(Array) -> String //",".join(["1","2","3"]) = "1,2,3"
  • componentsSeparatedByString(String) -> [String] //"1,2,3".csb(",") = ["1","2","3"]

Type Conversion

  • let d: Double = 37.5
  • let f: Float = 37.5
  • let x = Int(d)
  • let xd = Double(x)
  • let cfg = CGFloat(d)
  • let a = Array("abc") // a = ["a","b","c"]
  • let s = String(["a","b","c"]) //s = "abc"
  • let s = String(52)
  • let s = "\(37.5)"

Assertions

Debugging Aid

  • assert(() -> Bool, "message")

这个函数的参数是一个"autoclosure", 所以并不需要加{}
assert(validation() != nil , "the validation function returned nil")

Other Functions

你可能感兴趣的:(Developing iOS 8 Apps with Swift学习日记 ---- Class 4)