导言

在之前,我有写过关于 iOS 入门开发的一系列合集:iOS 入门系列合集,这其间既有关于 UIkit 的描绘,也有关于 SwiftUI的描绘;但首要是围绕 SwiftUI 打开的,关于 UIkit 仅仅轻描淡写

然而,上项目之后,用的结构又是 UIkit,因而 SwiftUI 的知识被逐渐忘记,突然有一天想要整理 UIkit 的学习道路,便回顾了一下 iOS 入门系列合集 的内容,在看到关于 SwiftUI 的数据状况和数据流部分时我有点懵了,一时间完全想不起来在 UIkit 中与之对应的完成是什么?因而本文便诞生了~

视图声明及布局

iOS 入门系列(二)这篇文章中有描绘 UIkit 和 SwiftUI 在视图和布局上的不同的界说及完成办法

这儿便再简要的总结一下:

  • 在视图声明上的区别
    • 运用的声明语法不同
    • SwiftUI 的语法更为简练和直观
    • 视图特点设置不同:UIkit 需求经过特点或办法来设置,SwiftUI 直接经过链式调用的办法设置
  • 在布局上的区别
    • UIKit 需求运用容器视图(如UIViewUIStackView)以及束缚来完成复杂的布局
    • SwiftUI 供给了VStackHStackZStack等更语义化的容器视图,以及内置的修饰符(如paddingspacing等),使得布局的界说更加简略

数据状况和数据流

iOS 入门系列(三) 一文中有对 SwiftUI 的数据状况和数据流的知识点进行介绍:经过特点包装器办理数据; 那么在 UIkit 中又是怎么完成关于数据状况的办理的呢?

概念科普

UIkit 本身并没有供给专门的机制来直接办理应用程序的数据状况。UIkit 首要重视用户界面的创立、显现和交互,而数据状况一般由应用程序的数据模型 (Model) 或控制器 (Controller) 类来办理

UIkit 供给了一些工具,如:署理 (Delegate)、闭包 (Closure) 、告诉中心 (NotificationCenter)、特点调查器等,用于在视图控制器、视图和模型之间传递数据和告诉数据状况的改变,以达到同步更新视图的意图;一起,UIkit 也供给了关于视图重绘、重排的内置办法进行视图的更新

因而,在 UIkit 应用程序中,数据状况的办理是开发人员的责任,一般经过创立和保护数据模型或控制器类来完成。这些类会包含应用程序的数据逻辑,包含数据状况的办理和更新。署理、闭包和告诉中心等工具可用于协助数据状况的传递和同步更新,但它们并不直接办理数据状况

可视化解析

关于 UIkit 和 SwiftUI 那些用法不同但最终完成相同的概念合集
上图分别画出了在 SwiftUI 和 UIkit 中怎么对视图进行更新的系列操作,能够很明显看出 SwiftUI 采用特点包装器直接能够省掉掉VC这一中间层,使视图的更新更简略直接;在 UIkit 中要完成视图与数据同步更新则需求凭借VC这一中间层并合作署理告诉中心闭包特点调查器来完成

拓展

署理、告诉中心概念

关于署理能够参阅 iOS 近期开发概念小结一文的delegate 就是一个特点? 部分的内容合作理解消化;

告诉中心的运用相对简略,由于是大局的告诉,所以只需求在发送告诉的当地界说告诉,然后在需求接纳告诉的当地注册并处理它即可,下面给出案例参阅:

发送告诉

import UIKit
// 界说告诉称号
let myNotificationName = Notification.Name("MyCustomNotification")
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 发送告诉
        NotificationCenter.default.post(name: myNotificationName, object: nil)
    }
}

接纳告诉

import UIKit
class AnotherViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 注册告诉
        NotificationCenter.default.addObserver(self, selector: #selector(handleCustomNotification), name: myNotificationName, object: nil)
    }
    // 处理告诉的办法
    @objc func handleCustomNotification() {
        print("Received custom notification")
    }
    deinit {
        // 当不再需求接纳告诉时,撤销注册告诉
        NotificationCenter.default.removeObserver(self, name: myNotificationName, object: nil)
    }
}

UIkit 视图重排、重绘

在上面现已提到过 UIkit 关于视图的重绘和重排的内置办法,这儿就简略的小结一下它们的一些区别:

重绘和重排概念

  • 重绘:修改视图上的文本、图片等可见内容
    • 调用draw(_:)办法,可自界说
  • 重排:修改视图的位置、尺度和布局特点
    • 调用layoutSubviews办法,可自界说
  • 简略总结:重绘功能耗费高于重排

UIkit 中重排的2种办法

  • setNeedsLayout():异步更新恳求,不会当即触发布局,而是在当时运行循环完毕后,体系会查看需求更新布局的视图,并在合适的时机履行layoutSubviews办法
  • layoutIfNeeded():用于强制当即履行布局的,不必等候体系的下一次布局更新

延伸概念

  • 体系会有多个事情循环,每个事情循环都处理不同类型的事情。UIKit 应用程序一般包含主 Run Loop 和任意数量的自界说 Run Loops
  • 主 Run Loop 是应用程序的首要事情循环,负责处理用户交互事情(如触摸事情、按钮点击等)以及其他体系事情
  • 自界说 Run Loops能够用于其他意图,例如:在后台履行任务
  • 每个 Run Loop 都有自己的循环周期,而且会不断运行,等候和处理事情。这有助于应用程序响应用户交互、网络恳求、计时器事情等

setNeedsLayout办法一般用于告知体系在当时 Run Loop 完毕时或下一个 Run Loop 中进行布局更新,以充分利用体系的事情循环来下降功能开销

SwiftUI 和 UIkit 中的 class 和 struct 运用

一起用过 SwiftUI 和 UIkit 结构的伙伴可能会注意到:在 SwiftUI 中一般是用 struct 创立视图,而在 UIkit 中却一般是用 class 创立视图,这其间有什么缘由吗?

其实,classstruct都是用来创立不同类型的数据结构的,仅仅由于它们本身的一些特性和这两个结构的特性所形成的这样一个现象

由于 SwiftUI 的视图一般是不可变的,这意味着当视图需求更新时,将创立一个新的视图实例。因而大多情况下是用 struct 来创立;而在 UIkit 中视图一般是可变的,会涉及到继承、引证,因而运用 class 来创立

小结

在 SwiftUI 中,经过特点包装器创立具有数据绑定的视图模型,在数据更改时,视图会自动更新以反映这些更改。这样的办法使得在 SwiftUI 中办理数据状况和更新视图更加直观和简化

在 UIkit 中,没有专门的机制来直接办理应用程序的数据状况。因而就需求凭借Viewcontroller 层合作着署理告诉中心闭包特点调查器来完成数据与视图的同步更新