Swift
2. mutating
struct A {
var a = 1
mutating func changeA() {
a = 2
}
}
var a = A()
a.changeA()
print(a.a)
3. 柯里化
func addTo(_ x: Int) -> (Int) -> Int {
return { y in
return x + y
}
}
let addTo3 = addTo(3)
addTo3(4)
addTo3(5)
4. 常用高阶函数
//map映射
let mapResult = [0,1,2,3].map { (i) -> String in
return "\(i)"
}
print(mapResult)//["0", "1", "2", "3"]
//compactMap丢弃nil映射
let compactMapResult = ["0","@","1","#","2","3"].compactMap { (s) -> Int? in
return Int(s)
}
print(compactMapResult)//[0, 1, 2, 3]
//filter过滤器
let filterResult = [0,1,2,3].filter { (i) -> Bool in
return i % 2 == 0
}
print(filterResult)//[0, 2]
//reduce合并
let reduceResult = [0,1,2,3].reduce(0) { (re, i) -> Int in
return re + i
}
print(reduceResult)//6
5. defer
延时执行,会在其所在作用域内所有语句执行完毕再执行 可以使得数据库连接、文件连接等关闭语句不一定非要写到作用域尾部,可以使用defer关键字和建立连接写到一起
func f() {
defer {
print(2)
}
print(1)
}
f()// 1\n 2\n
6. associatedtype
协议的泛型
protocol P {
associatedtype A
var p: A { get set }
func changeP() -> A
}
class C1: P {
typealias A = Int
var p: Int = 1
func changeP() -> Int {
p = 2
return p
}
}
class C2: P {
typealias A = String
var p: String = "a"
func changeP() -> String {
p = "b"
return p
}
}
let c1 = C1()
c1.changeP()
let c2 = C2()
c2.changeP()
7. final
限制继承和重写
//final限制继承
final class FinalClass {
}
//class SubClass: FinalClass {} //编译错误,无法继承final class
8. 访问控制
- open
- public
- internal
- file-private
- private
- open 在其它模块中可以访问和重写
- public 在其它模块中可以访问,但不可以重写
- internal 默认,在模块内部的多个文件内可以访问和重写
- file-private 在文件内部可以访问
- private 在类或结构体的内部可以访问
9. try! try?
//try! try?
func devide(_ a: Double, _ b: Double) throws -> Double {
enum DevideError: Error {
case ZeroError
}
guard b != Double(0) else {
throw DevideError.ZeroError
}
return a / b
}
print(try? devide(2, 1))//Optional(2.0)
//print(try! devide(2, 0)) //Fatal error崩溃退出
10. @autoclosure
//autoclosure把传进来的参数自动加上个闭包
func logIfTrue(_ predict: @autoclosure () -> Bool) {
if predict() {
print("True")
}
}
logIfTrue(2 > 1)
11. @escaping
import Foundation
// 逃逸闭包,在闭包所在的函数体执行完毕之后执行的闭包
func delay(callback: @escaping (Timer) -> Void) {
Timer(timeInterval: 1, repeats: false, block: callback).fire()
}
delay { _ in
print("escaping after 1 second")
}
12. @discardableResult
//在函数前加上@discardableResult,即使返回值没有被使用,编译器也不会提示
@discardableResult
func discardResult() -> Int {
return 1
}
discardResult()
13. 枚举关联值
enum Person {
case man(name:String)
case woman(name: String)
}
func whatName(_ person: Person) {
switch person {
case let .man(name: name):
print("man", name)
case let .woman(name: name):
print("woman", name)
}
}
whatName(.man(name: "1")) // man 1
whatName(.woman(name: "2")) // woman 2
14. 枚举封装
enum Week {
case Monday
case Tuesday
case Whitch(Int)
func printDay() {
switch self {
case .Monday:
print(1)
case .Tuesday:
print(2)
case .Whitch(let i):
print(i)
}
}
}
Week.Monday.printDay()
Week.Tuesday.printDay()
Week.Whitch(1).printDay()
15. 操作列表
//[.option1, .option2]
enum Option {
case option1
case option2
}
typealias Options = [Option]
func setOptions(_ options: Options) {
struct ParsedOptions {
var option1 = false
var option2 = false
init(_ options: Options) {
for op in options {
switch op {
case .option1:
option1 = true
case .option2:
option2 = true
}
}
}
}
print(ParsedOptions(options))
}
setOptions([.option1, .option2])
16. ??
//?? Optional默认值
let defaultNilValue = Int("@") ?? 0
print(defaultNilValue)
17. @propertyWrapper
// 用属性包装器来包裹
@propertyWrapper
struct AddOne {
private var x: Int
init() {
x = 0
}
var wrappedValue: Int {
get {
x + 1
}
set {
x = newValue
}
}
}
// 属性包装器不能写在模块顶层
struct Test {
@AddOne var addOne: Int
}
var test = Test()
print(test.addOne) // 1
test.addOne = 1
print(test.addOne) // 2
18. keyPath
struct A {
struct B {
struct C {
let value: String = "c"
}
let value: C = C()
}
let value: B = B()
var c: String {
get {
self[keyPath: \.value.value.value]
}
}
func keyPath(_ keyPath: KeyPath<A, String>) -> String {
return self[keyPath: keyPath]
}
}
let a = A()
a.value.value.value
let keyPath = \A.value.value.value
a[keyPath: keyPath]
a.keyPath(\.value.value.value)
a.c
19. 元素为值类型和引用类型的数组更改的区别
// 元素为值类型的数组只可以使用index更改数组
struct Value {
var property = 0
}
var valueArray: [Value] = .init(repeating: .init(), count: 3)
for index in 0..<valueArray.count {
valueArray[index].property += 1
}
dump(valueArray)
// 元素为引用类型的数组既可以使用index更改数组,又可以使用for-in循环更改数组
class Reference {
var property = 0
}
// 引用类型元素不可以使用Array(repeating:count:)来循环创建数组,否则创建出来的数组都是同一个引用
//var referenceArray: [Reference] = .init(repeating: .init(), count: 3)
var referenceArray: [Reference] = .init(AnyIterator(Reference.init).prefix(3))
for reference in referenceArray {
reference.property += 1
}
for index in 0..<referenceArray.count {
referenceArray[index].property += 1
}
dump(referenceArray)
20. 字典key和value同时映射
extension Dictionary {
func mapKeysAndValues<K, V>(_ transform: ((key: Key, value: Value)) throws -> (K, V)) rethrows -> [K: V] {
[K: V](uniqueKeysWithValues: try map(transform))
}
}
21. @_dynamicReplacement
class B {
dynamic func a() {
print("a")
}
}
extension B {
@_dynamicReplacement(for:a)
func c() {
print("b")
}
}
B().a()
22. 范型与协议共用时有可能会遇到丧失范型类型的情况
protocol P {
var a: Int { get }
}
extension P {
var a: Int {
0
}
}
struct T<M>: P {
}
extension T where M == Int {
var a: Int {
1
}
}
let t: P = T<Int>()
print(t.a) // 0 丧失类型T<Int>,变为P
print(T<Int>().a) // 1
protocol P {
var a: Int { get }
}
extension P {
var a: Int {
0
}
}
struct T: P {
var a: Int {
1
}
}
let t: P = T()
print(t.a) // 1 不会丧失类型
print(T().a) // 1
23. 切片slice是绝对索引而不是相对索引
print([0, 1, 2][1...].startIndex) // 1
print((1..<3).startIndex) // 1
print([0, 1, 2][1...][0]) // Fatal error: Index out of bounds
print((1..<3)[0]) // Fatal error: Index out of range
24. 类单例和结构体单例
class C {
static let shared = C()
var state = 0
}
struct T {
static var shared = T()
var state = 0
}
// 将shared赋值给其它变量的情况
let c = C.shared
c.state = 1
print(C.shared.state) // 1
var t = T.shared
t.state = 1
print(T.shared.state) // 0 没有改变
// 使用类名/结构体名直接调用的情况
C.shared.state = 2
T.shared.state = 2
print(C.shared.state) // 2
print(T.shared.state) // 2
25. Decimal解决浮点数运算比较问题
print((0.1 + 0.2) == 0.3) // false
print(Decimal(0.1) + Decimal(0.2) == Decimal(0.3)) // true
print(Double(truncating: (Decimal(0.1) + Decimal(0.2)) as NSNumber)) // 0.3
26. 库前缀名调用
public struct Reactive<Base> {
public let base: Base
init(_ base: Base) {
self.base = base
}
}
public protocol ReactiveCompatible {
associatedtype ReactiveBase
var rx: Reactive<ReactiveBase> { get }
}
extension ReactiveCompatible {
public var rx: Reactive<Self> {
Reactive(self)
}
}