本文为大地瓜原创,欢迎知识共享,转载请注明出处。
虽然你不注明出处我也没什么精力和你计较。
作者微信号:christgreenlaw
大地瓜在学习Stanford University的Developing iOS 11 Apps with Swift.
这里记录了一些小笔记。这部分是前三节。
这篇文章并不是这个教程的全部内容,只是大地瓜自己学习过程中想记录的一部分内容。
swift的optional是为了兼容OC的,optional有两个状态,set 和 not set。也就是要么有值要么无值。使用感叹号表示我们假定其一定有值,但如果你这样做了,加了感叹号,但其实本身无值,在访问时应用就会崩溃掉。问号则表示不保证有值,只是一个普通的optional。
struct和class在Swift中几乎是一样的东西。都有ivar,都有method
主要有以下两个区别:
- struct没有继承关系。
- struct是value type,class 是 reference type
数组、字典、int、string等等都是struct
value type是什么意思?
值类型在传递时会被拷贝。(Swift并不会无脑拷贝,只会将有修改的部分拷贝,也就是copy-on-write)
引用类型传递时,传递的可以认为是指针,使用的还是同一个对象。
- struct会默认得到一个init,其参数列表列出了所有的ivar。class得到的默认init只会是没有参数列表的init
Swift中的访问控制(Access Control)
internal-- default, it means "usable by any object in my app or framework"
private - this means "only callable from within this object"
private(set) - this means "this property is readable outside this object but not settable"
fileprivate - accessible by any code in this source file
public (for frameworks only) this can be used by objects outside my framework
open (for frameworks only) public and objects outside my framework can subclass this
不做framework开发的话不用在意后两个
比较好的做法是将所有的东西都标记为private,当我们发现这个东西需要外界调用时再取消private
Assertion 断言
假定某个条件为真则继续运行,否则就crash并打印一条error信息。
这个东西在自己测试开发时会有效,在产品中是无效的。
用于保护方法的实现,可以测试一些错误。
assert(一个bool,一个string错误信息)
Extensions
Add vars(properties) and methods to a class/struct/enum, even if you don't have the source code for that class/struct/enum.
注意以下限制:
- 你不能重写已有的method或property。(你只能添加新的)
- 添加的property不能有相关的storage(computed only)
这个extension和OC中的类扩展差别还是挺大的,OC里我没记错的话可以重写方法覆盖原来的方法,属性也是可以进行存储的。
最好是给某个类型添加相关的工具或功能,不要添加和这个类没关系的功能。
Optionals
先看enum
enum是class和struct之外的另一种数据结构。
enum只能有离散的状态(discrete states)
enum FastFoodMenuItem {
case hamburger
case fries
case drink
case cookie
}
enum是值类型,所以在传递时会被拷贝。
enum和struct都是值类型,传递时会进行复制,所以传递后你修改的是新的副本,而不是原来的那个,而class是引用类型,会传递自身,你修改一处,那么所有拥有这个class对象的,都会变化
每个case都可以有相关的数据(但不是非要有数据)
enum FastFoodMenuItem {
case hamburger(numberOfPatties: Int)
case fries(size: FryOrderSize)
case drink(String, ounces: Int)
//the unnamed String is the brand, e.g. "coke"
case cookie
}
//note that the drink case has 2 pieces of associated data(one of the "unnamed")
// in the example above, FryOrderSize would also probably be an enum
enum FryOrderSize {
case large
case small
}
使用enum
let menuItem: FastFoodMenuItem = FastFoodMenuItem.hamburger(patties: 2)
let otherItem: FastFoodMenuItem = FastFoodMenuItem.cookie
如果要使用类型推断
let menuItem = FastFoodMenuItem.hamburger(patties: 2)
let otherItem: FastFoodMenuItem = .cookie
//以上都是可以的
//但是不可以像这样
let otherItem = .cookie
//这个不难理解吧。。。。
也就是说,只能推断一侧。如果你什么都不给的话,那如何推断呢?
一般使用enum判断状态时,使用switch
某个分支你不想做什么就用break
switch
语句必须遍历所有情况,不能有剩余,如果你不关心某些状态,记得使用default
swift中的switch
默认是不会fall through
的,不会继续执行下一个case
的
enum是可以有method的,以及computed properties,不可以有stored properties
enum FastFoodMenuItem {
case hamburger(numberOfPatties: Int)
case fries(size: FryOrderSize)
case drink(String, ounces: Int)
//the unnamed String is the brand, e.g. "coke"
case cookie
func isIncludedInSpecialOrder(number: Int) -> Bool {}
var calories: Int { //calculate and return caloric value here }
}
enum自己的method中,可以对自己的状态进行判断(switch self)。但不可以在property的get中进行判断。
enum FastFoodMenuItem {
···
func isIncludedInSpecialOrder(number: Int) -> Bool {
switch self {
case .hamburger(let pattyCount): return pattyCount == number
case .fries, . cookie: return true//fries and cookie in every special order
case .drink(_, let ounces): return ounces == 16//16oz drink of any kind
}
}
var calories: Int { //calculate and return caloric value here }
}
在enum的method中甚至可以对自己进行修改(更改自己的类型)
enum FastFoodMenuItem {
···
mutating func switchToBeingACookie() {
self = .cookie//此时将自身转换为cookie了,不管你原来是hamburger还是fries还是什么
}
}
需要注意的是,mutating
是必须要写的,因为enum是一个值类型,copy on write。(struct中也需要写mutating
)
说了这么多,Optional其实就是个enum。
大概就是这样:
enum Optional {
//a generic type, like Array or Dictionary
case none
case some()//the some case has associated data of type T
}
但是它很特殊,有许多特殊的语法。
strong是默认的,一般我们不需要写出来。
weak:如果别人都不感兴趣了,我也就不感兴趣了,把我设置成nil就好。
那么既然weak是可以设置为nil的,我们很显然可以知道只有optional的引用类型才可能是weak。别的地方是用不到weak的。
常见的两个weak情景,一个就是outlet,另一个是delegate。别的地方真的很少用weak了。
weak指针是不会将对象保留在heap中的。unowned:别引用计数我。我指向某个地方,但是你别计数我。我保证没有引用计数时(heap中没有这个对象时我绝对不会访问这里的,但是你一旦访问的话就会crash)这个真的几乎不用,太危险了。
一般用unowned来干嘛呢?解决引用循环。
closure经常产生引用循环。