Swift学习理解小记

149 阅读4分钟

纯粹是学习Swift的过程遇到的些许问题, 左下记录

面向协议

Swift是第一款面向协议编程的语言, 初学的时候很难理解面向协议, 为什么使用面向协议的方式, 面向协议的优势是什么.

首先, 我们来看一下面向对象, 面向对象的核心是封装和继承, 封装的本质是将相类似事物的相同特征抽象到一起进行建模. 但是这一套方式有一个问题, 就是实际的事物往往是一系列特征的集合, 面向对象的建模只能抽象出在类似事物的相同特征, 而不能抽象出不同事物的相同特征.

所以, 我们很难在不同继承关系的类里公用代码.通常我们会使用新建一个基类,或者依赖注入的方式.前者看起来是很靠谱的解决方法,但是长此以往会让基类变得职责不明确,而后者则会添加多余的依赖关系,可能并非是我们想要的.或者像c++那样采用多继承的方式,但是同样会产生一个著名的问题:菱形缺陷.

参考链接:

猫神:面向协议编程与 Cocoa 的邂逅

关键字

mutating:该关键字用于修饰func,

无mutating
无mutating报错

mutating
mutating正确用法

主要是用来在函数中访问structenum的变量 classstatic用来修饰函数的时候,都能表示为类方法,staticclass多一个final关键字的作用,即不能被子类重写.

泛型

泛型的话,有点像多态,就是在类型不确定的时候,使用泛型代替表示,类似于传入的参数为基类,使用如下:

泛型
泛型在函数中的使用

where T: Encodable表示当T是遵循Encodable协议的类.

闭包

Swift中的闭包, 类似Objective-C中的Block 定义一个闭包:

声明闭包
定义一个闭包
escaping:逃逸闭包, 目前缺省时默认为逃逸闭包. 逃逸闭包的生命周期长于相关函数, 当函数调用结束后, 逃逸闭包仍然可以继续执行 noescaping:用于修饰非逃逸闭包, 顾名思义, 与逃逸闭包相反, 把闭包作为参数传递给函数, 该闭包在函数调用过程中运行.

解决循环引用

解决闭包循环引用
解决闭包循环引用写法

结构体

Swift中, 声明结构体的方式与类class相同, 关键字使用struct.

什么时候使用结构体或者类? 面向协议的编程方式趋向于使用struct+protocol, 也就是结构体+协议 的方式代替类class, 在搞清楚这个问题之前, 我们首先明白结构体struct和类class究竟有什么不同.

1.结构体是值类型, 而类则是引用类型. 这句话意味着`struct`是的复制都是值传递, 而非引用类型的引用计数+1
2.`class`可以实现继承, `struct`则并不具备.
3.`class`在声明的时候需要给出变量的初始值, 或者使用可选类型代替, 而`struct`不需要

个人理解: swift是面向协议编程, struct+protocol的方式更符合这个理念.

Any, AnyObject, AnyClass

AnyAnyObject是为了与Objective-C混编而妥协的产物, AnyObject是为了代替Objective-C中的id类型, 熟悉Objective-C的朋友肯定知道, 使用id声明的时候, 编译器不会对class的类型做检查, 但是他仅能用于class, 而swift中的DictionaryString等是struct, 于是Any的作用就来了, Any可以表示任意类型,甚至包括方法 func 类型, 而AnyClassAnyObject的别名, 系统API定义如下:

        `public typealias AnyClass = AnyObject.Type`

swift-runtime

使用class_copyPropertyList等方法时, 该swift类需要继承自NSObject类,且在声明时需使用@objcMembers修饰, 否则获取不到. 代码如下:

runtime声明model

即便是这样声明了, 还是会发现class_copyPropertyList获取到的变量不全, class_copyIvarList方法倒是可以获取到完整的属性, 运行发现基础类型都无法通过class_copyPropertyList获取到, 解决这个问题需要在声明的时候赋值