1.在swift中,类(class)作为引用类型,类的实例其实不太应该被称为对象(object),就应该是实例.
2."==="用于判断两个变量是否引用同一个实例,需要用在class的实例上,"=="需要相应类型实现这个运算符函数.
3.swift中也有指针,比如withUnsafeMutablePointer.
4.如果把函数赋值给一个变量,或者作为函数的参数或者返回值,这样的函数叫做闭包,但是不仅是如此,即使是func定义的函数,只要包含了外部变量,它也是一个闭包.
5.所谓方法,就是定义在类或者协议中的函数,不是方法的函数可以叫做自由函数.
6.swift在runtime中的表现,函数分为静态派发和动态派发,自由函数和结构体里调用的方法是静态派发,编译器会直接将函数调用替换为函数内的代码;类和协议的方法可能是动态派发的,@objc的类或协议的方法使用objc_msgSend,普通的方法使用Selector.
7.swift通过继承,方法的复写(重写),重载(为同一个方法实现多种类型的实现),和泛型来实现多态.泛型的方法是静态的.
8.在swift中,集合类型被赋值给另一个变量时,数组的内容会被复制.作为参数专递给函数时,也是一样的.而OC的NSMutableArray等,需要手动copy.
这种频繁的复制并不会造成性能压力,swift中的集合类型都使用了"写时复制"的特性,在下面的例子中,append调用之前x和y是共用的同一份,写实复制也可以在自定义的类型中实现.


9.swift为Array提供了很多OC没有的方法,并且移除了C风格的for循环语法,这是因为swift不鼓励索引计算;
first和last是可选值,removelast在数组为空是会crash,而popLast在数组为空时,什么都不做.

10.数组变形,swift提供了一系列Element方法
例如使用map来对元素进行变换,通过闭包,每个元素获得一个新元素,最终返回一个新数组.
map 可以将模板代码分离出来,这些模板代码并不会随着每次调用发生变动,发生变动的是那些功能代码,也就是如何变换每个元素的逻辑代码。map 函数通过接受调用者所提供的变换函数作为参数来做到这一点。


11.类似map的这种设计叫做函数行为参数化,在swift标准库中很多这样将行为进行参数化的设计模式.这些非常方便,例如排序people.sort { 1.age };是否包含满足某个条件的元素people.contains { $0.age < 18 };等等



这些方法都是这样的结构:
extension Array {
func map<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
result.reserveCapacity(count)
for x in self {
result.append(transform(x))
}
return result
}
}
据此,也可以自定义一些类似的方法.
12.map不一定是有序的,下面这段代码是创建了一个临时遍历runing,每个元素变成前面所有元素的和
extension Array {
func accumulate<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) -> Result) -> [Result]{
var running = initialResult
return map { next in
running = nextPartialResult(running, next)
return running
}
}
}
//调用
[1,2,3,4].accumulate(0, +) // [1, 3, 6, 10]
这里是假设map是按照下标0开始迭代,这样做不可靠,应该使用for循环更合理.
13.map 和 filter 都作用在一个数组上,并产生另一个新的、经过修改的数组。不过有时候,你可
能会想把所有元素合并为一个新的值。比如,要是我们想将元素的值全部加起来.

使用reduce方法,0是起始值,后面是一个行为,也可以直接写成运算符方法
// let sum = fibs.reduce(0) { partialResult, num in
// partialResult + num
// }
let sum = fibs.reduce(0, +)
输出值的类型可以任意
let sum2 = fibs.reduce("") { partialResult, num in
partialResult + "\(num)"
}
reduce的实现
extension Array {
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) -> Result) -> Result {
var result = initialResult
for x in self {
result = nextPartialResult(result, x)
}
return result
}
}
14.compactMap相当于map加上filter
let possibleNumbers = ["1", "2", "three", "///4///", "5"]
let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
// [1, 2, nil, nil, 5]
let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
// [1, 2, 5]
15.数组和字符串都有切片,切片是一种表示方式,数据仍然是原来的数组或者字符串
let fibs = [0,1,2,3]
let sli = fibs[1...]
let ff = Array(sli)
sli的类型是ArraySlice<Int>,这里的关键在于数组fibs并没有被复制,当调用第三行时,内容才被复制
16.合并字典 merge(_:uniquingKeysWith:),也是一个函数行为参数化的方法
合并首先会把key取并集,如果两个字典都存在某个key,通过行为参数设置选择左边的还是右边的.
let defaultSettings: [String:Setting] = [ "Airplane Mode": .bool(false), "Name": .text("My iPhone")]
var settings = defaultSettings
let overriddenSettings: [String:Setting] = ["Name": .text("Jane's iPhone")]
settings.merge(overriddenSettings) { _, key1 in
key1
}
// settings.merge(overriddenSettings, uniquingKeysWith: { $1 })
17.字典是Sequence类型,因此它有一个map方法,返回一个数组,另外还有一个mapValue方法来处理每个值
let dic = ["aa":1,"bb":2]
let arr = dic.map({ $0.value })
print(arr)//[2, 1]
let dic2 = dic.mapValues { v in
v * 2
}
print(dic2) //["bb": 4, "aa": 2]
18.关于Hashable
字典是哈希表,通过key的哈希值来指定它的位置,以及对应的存储,因此key的类型要遵循Hashable协议,基本类型字符串,整数,浮点数以及布尔值都遵循Hashable,如果想用非值类型来作为key,则需要手动遵循Hashable并实现hashValue和"=="运算符两个方法,相同的两个实例哈希值必须相同,反过来不一定;并且做这些的时候还需要考虑哈希值的计算效率以及回避哈希碰撞
19.set也是哈希表,相当于只存了key的字典,因此元素需要遵循Hashable,set遵循ExpressibleByArrayLiteral协议,可以用数组字面量赋值,
let naturals: Set = [1, 2, 3, 2] //[2,1,3]
集合提供了一些数学意义上的方法在协议 SetAlgebra中,比如交集,并集,补集
//补集
let iPods: Set = ["iPod touch", "iPod nano", "iPod mini", "iPod shuffe", "iPod Classic"]
let discontinuedIPods: Set = ["iPod mini", "iPod Classic", "iPod nano", "iPod shuffe"]
let currentIPods = iPods.subtracting(discontinuedIPods) // ["iPod touch"]
//交集
let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"]
let iPodsWithTouch = iPods.intersection(touchscreen)
// ["iPod touch", "iPod nano"]
//并集
var discontinued: Set = ["iBook", "Powerbook", "Power Mac"]
discontinued.formUnion(discontinuedIPods)
//["iBook", "Powerbook", "Power Mac", "iPod Classic", "iPod mini", "iPod shuffe", "iPod nano"]
给Array 添加一个方法,实现有序集合去重
extension Array where Element : Hashable{
func unique() -> [Element]{
var seen : Set<Element> = []
return filter { el in
if seen.contains(el){
return false
}else{
seen.insert(el)
return true
}
}
}
}
20.Range既非集合又非序列,因此不能迭代,但是却可以写出for i in 0..<10,这是因为 0..<10 的类型其实是一个 CountableRange<Int>类型,叫做可数范围,与Range不同,它的元素类型需要遵守Strideable 协议 (以整数为步⻓);
如果元素类型仅仅只是满足 Comparable,它对应的是“普通” 范围 (这是范围元素的最小要求),那些元素满足Strideable,并且使用整数作为步⻓的范围则是可数范围;只有后一种范围是集合类型.

网友评论