写时拷贝 copy-on-write
swift中Array,Dictionary和Set集合类型运用了此技术。 原理:当一个集合在被修改时,会先检查其引用是否唯一。是,那就那就直接变更。如果还有其他引用,那么就会新复制一份,再进行变更。
filter reduce map&compactMap
filter
使用闭包中的规则去删选元素,返回一个集合
let packages = [
Package(name: "Swift高阶函数编程", number: 1, price: 80.0, address: "中关村"),
Package(name: "Swift面向协议编程", number: 2, price: 80.0, address: "西二旗"),
Package(name: "Swift基础", number: 3, price: 35.0, address: "798"),
Package(name: "Swift进阶", number: 4, price: 50.0, address: "望京soho")
]
//filter :使用闭包中的规则去删选元素,返回一个集合
let packages_filter = packages.filter {(package)-> Bool in
return package.price == 80.0
}
//简化版
//let packages_filter = packages.filter {$0.price == 80.0}
print(packages_filter)
打印
Package(name: "Swift高阶函数编程", number: 1, price: 80.0, address: "中关村")
Package(name: "Swift面向协议编程", number: 2, price: 80.0, address: "西二旗")
reduce
接受一个初始值,并使用闭包中的规则合并遍历的元素
let reduceName = packages.reduce("xxx前缀xxx") {$0 + $1.name}
print(reduceName)
打印
xxx前缀xxxSwift高阶函数编程Swift面向协议编程Swift基础Swift进阶
map
通过闭包中的规则返回一个新的集合
let packages_map = packages.map{ $0.name + "riceFun" }
print(packages_map)
打印
["Swift高阶函数编程riceFun", "Swift面向协议编程riceFun", "riceFun", "Swift进阶riceFun"]
compactMap
和map相似,但是它能自动去掉空值
let numbers = ["1", "2", "three", "///5///", "5"]
let numbers_map = numbers.map { (number) -> Int? in
return Int(number)
}
print(numbers_map)
//[Optional(1), Optional(2), nil, nil, Optional(5)]
let numbers_compactMap = numbers.compactMap { (number) -> Int? in
return Int(number)
}
print(numbers_compactMap)
//[1, 2, 5]
Swift & OC
Swift & OC-共同点
- 相同概念:引用计数、ARC(自动引用计数)、属性、协议、接口、初始化、扩展类、命名参数、匿名函数等
- 公用一套运行时环境,
Swift的类型可以桥接到OC,反之亦然
Swift & OC-区别
- Swift:可选类型,注重安全,相比于OC中的nil更加安全和简明
- Swift:面向协议、函数式编程、面向对象;OC:面向对象
- Swift:注重值类型;OC:注重指针和引用
- Swift:语法简洁;OC:语法冗杂
- Swift:支持泛型:OC:只有集合类型才支持泛型
- Swift:有各种方便快捷的高阶函数(函数式编程) eg: (Swift的标准数组支持三个高阶函数:
map,filter和reduce,以及map的扩展flatMap);OC:不支持 - Swift: 支持元组类型,把多个值组合成复合值;OC:不支持
面向协议 & 面向对象
1. 对抽象数据的使用方式
- 面向对象采用的是继承
- 面向协议采用的是遵守协议
eg:
面向对象:飞机、火车、汽车继承于交通工具类,马、老虎继承于动物类,但是马也有作为交通工具的能力,这样就能难划分了整理了。但是面向协议就只要抽离出交通工具的能力作为一个协议,只要遵守协议就具备这个能力。
2. 协议可以被类、结构体和枚举遵守,而类层级约束为类类型
3. 总结:
面向协议相对于面向对象来说更具有可伸缩性和可重用性,并且在编程的过程中更加模块化,通过协议以及协议扩展替代一个庞大的基类,这在大规模系统编程中会有很大的便捷之处。
unowned weak
unowned(无主引用)
- 无主引用不能设置为nil,因为非可选类型的变量不允许被赋值为nil
- 用于一个是可选类型,一个是非可选类型
class Customer {
let name: String
var card: CreditCard?//人不一定有卡
init(name: String) {
self.name = name
}
deinit { print("\(name) is being deinitialized") }
}
########
class CreditCard {
let number: UInt64
unowned let customer: Customer//卡一定有持有人
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
weak
- 用于两个都是可选类型
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak var tenant: Person? //公寓的房客可能为空所以声明为weak
deinit { print("Apartment \(unit) is being deinitialized") }
}
闭包中使用
//weak 防止循环引用
student?.giveAnswerClosure = { [weak self] answer in
self?.isRight = answer == 1 ? true : false
}
optional
Optional 是一个泛型枚举,大致定义如下:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
可选值,专门用来处理数据可能为空的情况。在类型后添加一个问号来标识这个数据是可选值类型,表明这个变量盒子包含了两种可能性:有值或者为空。
var errorCode : Int?
errorCode = 100
errorCode = nil
Unwarpping optionals(解包)
var errorCode : Int? = 30
print(result)
打印: Optional(30)
Force unwrapping (强制解包 !):有危险
var authorName: String? = "Mike"
var unwrappedAuthorName = authorName!
print("Author is \(unwrappedAuthorName)")
打印:Author is Mike
Optional binding(可选值绑定):更安全的访问可选值的内容,
if let unwrappedAuthorName = authorName {
print("Author is \(unwrappedAuthorName)")
} else {
print("No author.")
}
可选值绑定一般搭配guard
func maybePrintSides(shape: String) {
guard let sides = calculateNumberOfSides(shape: shape) else {
print("I don't know the number of sides for \(shape).")
return
}
print("A \(shape) has \(sides) sides.")
}
空值合并 ??:swift有一种更好用的方式去解包可选值。不管可选值有没有值,如果没有值就使用默认值,这种方式就是空值合并。
var optionalInt: Int? = 10
var mustHaveResult = optionalInt ?? 0
class和struct 的区别
class为类,struct为结构体, 类是引用类型, 结构体为值类型struct定义结构体类型时其成员可以没有初始值,class不可以,会报错struct自动生成构造器,class需要手动生成mutating function:struct的方法修改property值时要加上mutating,class,不需要struct不能继承,class可以继承。struct比class更“轻量级”,struct分配在栈中,class分配在堆中。
Struct 作为数据模型的注意事项
优点:
- 内存:
Struct是用值类型传递的,它们没有引用计数 - 安全:由于他们没有引用数,他们不会因为循环引用导致内存泄漏
- 速度: 值类型通常来说是以栈的形式分配的,而不是用堆。因此他们比
Class要快很多! - 拷贝:
Objective-C里拷贝一个对象,你必须选用正确的拷贝类型(深拷贝、浅拷贝),而值类型的拷贝则非常轻松! - 线程安全 :值类型是自动线程安全的。无论你从哪个线程去访问你的
Struct,都非常简单。
缺点:
- 混合开发时,
oc无法调用swift中的struct Struct不能相互继承。Struct不能被序列化成 NSData 对象。不能使用NSUserDefaults
所以:如果模型较小,并且无需继承、无需储存到
NSUserDefault或者无需Objective-C使用时,建议使用Struct。
guard和if
guard 和 if 类似, 不同的是, guard 总是有一个else语句, 如果表达式是假或者值绑定失败的时候, 会执行 else 语句, 且在 else 语句中一定要停止函数调用
open > public > internal > fileprivate > private
private:只有当前类可以访问。fileprivate:当前文件内可以访问internal:默认访问级别,一般不写,可以在整个模块中访问:eg:如果在框架/库外,那就不能访问,内部能访问public:都能访问,但不能被override和继承open:都能访问,包括override和继承