Swift 开发中不可不知的 Tips 集合

640?wx_fmt=jpeg

作者|Dariel

  1. 如何在 Swift  中实现多继承?

  2. 怎么做到自动检查 Controller 被销毁?

  3. Swift 中的 KVO 可以不基于 Runtime 吗?

  4. 如何优雅的实现 TableView 刷新动效?

  5. 不需管理 key 是否还可以使用 UserDefaults

1. 如何在 Swift 中实现多继承?

1.1 实现过程

Swift 本身并不支持多继承,但我们可以根据已有的 API 去实现。

Swift 中的类可以遵守多个协议,但是只可以继承一个类,而值类型(结构体和枚举)只能遵守单个或多个协议,不能做继承操作。

多继承的实现:协议的方法可以在该协议的extension中实现

640?wx_fmt=png

无论是结构体还是类还是枚举都可以遵守多个协议,所以多继承就这么做到了。

1.2 通过多继承为 UIView 扩展方法

640?wx_fmt=jpeg

640?wx_fmt=png

640?wx_fmt=gif

2. 怎么做到自动检查 Controller 被销毁?

检查内存泄漏除了使用 Instruments,还有查看控制器 pop 或 dismiss 后是否被销毁,后者相对来说更方便一点。但老是盯着析构函数 deinit 看日志输出是否有点麻烦呢?

UIViewController 有提供两个不知名的属性: 

  1. isBeingDismissed: 当modal出来的控制器被 dismiss 后的值为 true

  2. isMovingFromParent: 在控制器的堆栈中,如果当前控制器从父控制器中移除,值会变成 true

如果这两个属性都为 true,表明控制器马上要被销毁了,但这是由 ARC 去做内存管理,我们并不知道多久之后被销毁,简单起见就设个 2 秒吧。

640?wx_fmt=png

我们把这个方法添加到 viewDidDisappear(_:) 

640?wx_fmt=png

如果发生循环引用,控制就不会被销毁,会触发 assert 报错。

3. Swift中的 KVO 可以不基于 Runtime 吗?

Swift 并没有在语言层级上支持 KVO,如果要使用必须导入 Foundation 框架,被观察对象必须继承自 NSObject,这种实现方式显然不够优雅。 

KVO 本质上还是通过拿到属性的 set 方法去搞事情,基于这样的原理我们可以自己去实现。

3.1 实现

话不多说,直接贴代码,新建一个 Observable 文件

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

使用起来和 KVO 差不多。

3.2 使用

需要监听的类

public class User {
    // 监听的属性需要是 Observable 类型
    public let name: Observable<String>    
    public init(name: String) {
        self.name = Observable(name)
    }
}

使用

// 创建对象
let user = User(name: "Made")
// 设置监听
user.name.addObserver(self, options: [.new]) { name, change in
    print("name:\(name), change:\(change)")
}
// 修改对象的属性
user.name.value = "Amel"  
// 这时就可以被监听到

// 移除监听
user.name.removeObserver(self)

注意: 在使用过程中,如果改变 value,addObserver方法不调用,很有可能是 Observer 对象已经被释放掉了。

4. 如何优雅的实现 TableView 刷新动效?
1. 简单的实现

我们都知道TableView的刷新动效是设置在tableView(_:,willDisplay:,forRowAt:)这个方法中的。

640?wx_fmt=png

这样一个简单的淡入效果就 OK 了,但这样做显然不够优雅,我们如果要在多个TableView使用这个效果该怎样封装呢?

2. 使用工厂设计模式进行封装

2.1 creator(创建者): Animator,用来传入参数,和设置动画640?wx_fmt=png
2.2  product(产品): AnimationFactory,用来设置不同的动画类型

640?wx_fmt=png

将所有的动画设置封装在 Animation 的闭包中。

最后我们就可以在tableView(_:,willDisplay:,forRowAt:)这个方法中使用如下代码,就实现最终效果

640?wx_fmt=png

640?wx_fmt=gif

5. 不需管理 key是否还可以使用 UserDefaults ?

用来做简单数据存储的 Preference 在我们的日常开发中使用的还是比较多的,但使用起来总感觉不那么方便。比如说需要去手动管理 key,之前是这样做的。

640?wx_fmt=png

我们可以通过使用 #function 避免手动管理 key,在存储和读取数据时调动的 set 和 get 方法也可以交给目标属性默认的 set 和 get 方法去做,。

640?wx_fmt=png

640?wx_fmt=png

在测试环节经常需要在测试服和正式服来回切换,为了避免老是打包,我们可以利用 UserDefaults 去更改服务器地址,在适当的位置(可以是个测试页面)加个 UISwitch,然后设置 serverUrl 的值。

UserDefaults 有性能问题吗?UserDefaults 是带缓存的。它会把访问到的 key 缓存到内存中,下次再访问时,如果内存中命中就直接访问,如果未命中再从文件中载入。它还会时不时调用同步方法来保证内存与文件中的数据的一致性,有时在写入一个值后也最好调用下这个方法来保证数据真正写入文件。

更多

限于篇幅原因这里分享部分Tips,更多内容如 使用面向协议实现 app 的主题功能,线程安全: 互斥锁和自旋锁,给UIViewController添加静态Cell 等点击 阅读原文 查看,本篇来自读者 Dariel 投稿,这里也欢迎更多的读者朋友推荐分享。

推荐阅读:

  1. https://github.com/DarielChen/SwiftTips

  2. 2019 让自己变的更加优秀(文末新年福利)

  3. 手摸手带你玩转Xcode Extensions

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值