前言

在学习SwiftUI所有的地方,视图元素都定义一个struct并实现View协议,该协议定义body变量返回View类型。

但是为什么,这里一直是指定的struct, 而不是class呢?

尝试使用class

如果你使用class 在SwiftUI中定义一个View,那么你将遇到一个编译器的错误

Protocol 'View' requirement '_makeView(view:inputs:)' cannot be satisfied by a non-final class ('ContentView') because it uses 'Self' in a non-parameter, non-result type position



错误的含义是,代码中使用了ContentView作为参数,如果ContentView有子类,那么将产生未定义的行为,必须限制ContentView没有子类,因此需要加上final修饰

上面的错误和这里类似:

https://stackoverflow.com/questions/40270118/protocol-requirement-cannot-be-satisfied-by-a-non-final-class-because-it-uses-s

加上final修饰之后,代码可以编译,运行之后直接崩溃:

SwiftUI/CustomView.swift:49: Fatal error: views must be value types (either a struct or an enum); ContentView is a class.
2022-02-23 15:41:34.418714+0800 SwiftClassUI[98636:8723744] SwiftUI/CustomView.swift:49: Fatal error: views must be value types (either a struct or an enum); ContentView is a class.



遇到断言错误,这个是SwiftUI限制只能使用struct或者枚举

为什么SwiftUI限制使用struct

经过搜索,大致有两个地方说明原因:

  • 一个是stackoverflow上说,因为SwiftUI中使用到了@State修饰状态,将和state和当前view进行绑定,如果是class,会遇到问题
  • 而是2019年的wwdc, swiftui_essentials, 其中有一个点提到了SwiftUI为什么采用struct而不是像UIKit一样的class

If you're coming from UIKit or AppKitt, you've probably gotten used to views being defined as classes that inherit from a common view superclass instead of as structs conforming to protocols.
For example, custom views in UIKit inherit from the UIView superclass.
And UIView defines storage for common view properties like alpha and backgroundColor.
Let's imagine we built our OrderHistory using UIKit instead of SwiftUI.
Our Custom View would inherit the stored properties of UIView as well as adding more properties for its own custom behavior.
So how is SwiftUI different than this? Well, remember that in SwiftUI we represent those same kinds of common view properties as separate modifiers instead, like we did for opacity and background.
And each of these modifiers creates their own view.
And this means that the storage for those properties is distributed across our view hierarchy in each of these modifier views instead of being inherited by every individual view.
Now this allows our views to be lighter weight, optimizing their storage for just their unique purpose.
And in this world, it makes a lot of sense that view just becomes a protocol because it's no longer needing to serve a common storage template for all of your views.
But what does this view protocol actually do? Well, let's remember our conceptual definition of a view.
Which is that a view defines a piece of our UI and we build bigger views by composing together smaller views.
And that's all that the view protocol does.
It defines a piece of our view hierarchy, giving it a name so that it can be composed and reused across your entire app.
And each concrete type of view is just an encapsulation of some other view representing its contents in its body property and all of the inputs required to create that view represented by its properties.
Now the actual protocol just defines that one body property returning just another kind of view.
But look

总结

  • struct相比class,能节省更多空间,有时候不需要继承父类中一些不需要的属性
  • struct相比class,操作更快,struct在栈上分配空间更加快
  • struct符合SwiftUI中的设计思路,界面是简单单一的,数据变化,UI就发生变化,数据不会在多处引用

为什么SwiftUI使用struct, 限制使用class的更多相关文章

  1. 从用SwiftUI搭建项目说起

    前言 后续这个SwiftUI分类的文章全部都是针对SwiftUI的日常学习和理解写的,自己利用Swift写的第二个项目也顺利上线后续的需求也不是特着急,最近正好有空就利用这段时间补一下自己对Swift ...

  2. [Android开发学iOS系列] iOS写UI的几种方式

    [Android开发学iOS系列] iOS写UI的几种方式 作为一个现代化的平台, iOS的发展也经历了好几个时代. 本文讲讲iOS写UI的几种主要方式和各自的特点. iOS写UI的方式 在iOS中写 ...

  3. SwiftUI 官方教程(八)

    8. 动态生成预览 接下来,我们会在 LandmarkList_Previews 中添加代码以在不同的设备尺寸上渲染列表.默认情况下,预览会以当前的 scheme 中设备的大小进行渲染.我们可以通过调 ...

  4. SwiftUI 官方教程(七)

    7. 给子 View 传递数据 LandmarkDetail 现在依然使用硬编码的数据来显示地标.像 LandmarkRow 一样,LandmarkDetail 类型和它组合的其他 view 都需要一 ...

  5. SwiftUI 官方教程(六)

    6. 在列表和详情之间设置导航 虽然列表已经能显示了,但是我们还不能通过点击单个地标来查看地标详情页面.SwiftUI教程 把 list 嵌入一个 NavigationView 中,并把每个 row  ...

  6. SwiftUI 官方教程(五)

    SwiftUI官方教程(五) 5. 同时使用 UIKit 和 SwiftUI 至此,我们已准备好创建 map view 了,接下来使用 MapKit 中的 MKMapView 类来渲染地图. 在 Sw ...

  7. SwiftUI 官方教程(四)

    SwiftUI 官方教程(四) 4. 自定义 Image View 搞定名称和位置 view 后,我们来给地标添加图片. 这不需要添加很多代码,只需要创建一个自定义 view,然后给图片加上遮罩.边框 ...

  8. SwiftUI 官方教程(三)

    3. 用 Stacks 组合 View 在上一节创建标题 view 后,我们来添加 text view,它用来显示地标的详细信息,比如公园的名称和所在的州. 在创建 SwiftUI view 时,我们 ...

  9. SwiftUI 官方教程(二)

    SwiftUI 官方教程(二) 2. 自定义 Text View 为了自定义 view 的显示,我们可以自己更改代码,或者使用 inspector 来帮助我们编写代码. 在构建 Landmarks 的 ...

  10. SwiftUI 官方教程(一)

    完整中文教程及代码请查看 https://github.com/WillieWangWei/SwiftUI-Tutorials   创建和组合 View 此部分将指引你构建一个发现和分享您喜爱地方的 ...

随机推荐

  1. 重新整理.net core 计1400篇[十] (.net core 中的依赖注入的服务的生命周期)

    前言 首先我们知道一个东西,那就是生命周期和timelife 的配置有关. 正文 首先看下IServiceProvider的数据结构: 其数据结构是一颗树: 我是一个抽象画家,红色部分是IServic ...

  2. 面试题 02.07(Java). 链表相交(简单)

    题目: 本题与:力扣160相交链表 一致 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点.如果两个链表没有交点,返回 null . 图示两个链表在节点 c ...

  3. 力扣1112(MySQL)-每位学生的最高成绩(中等)

    题目: 表:Enrollments (student_id, course_id) 是该表的主键. 问题编写一个 SQL 查询,查询每位学生获得的最高成绩和它所对应的科目,若科目成绩并列,取 cour ...

  4. 力扣577(MySQL)-员工奖金(简单)

    题目: 问题:选出所有 bonus < 1000 的员工的 name 及其 bonus.Employee 表单,empId 是这张表单的主关键字 Bonus 表单,empId 是这张表单的主关键 ...

  5. 力扣202(java&python)-快乐数(简单)

    题目: 编写一个算法来判断一个数 n 是不是快乐数. 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和.然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终 ...

  6. 使用日志上下文聚合插件使能上下文查询及Livetail

    简介: 日志上下文浏览是排查业务故障时常用的方式,但受限于Logtail插件系统的设计,在Logtail 1.2.1版本前,如果用户使用Logtail插件来处理日志或采集容器的标准输出,那么用户将无法 ...

  7. 入选 SIGMOD2021 的时间序列多周期检测通用框架 RobustPeriod 如何支撑阿里业务场景?

    简介: 本文除了介绍RobustPeriod的核心技术亮点,还将重点解释如何将它构筑成服务来解决阿里云的业务痛点. 近日,由阿里云计算平台和阿里云达摩院合作的时序多周期检测相关论文RobustPeri ...

  8. SAE助力「海底小纵队学英语」全面拥抱Serverless,节省25%以上成本

    简介: 阿里云Serveless应用引擎SAE 具备免运维IaaS.按需使用.按量计费.低门槛服务应用上云,并且支持多种语言和高弹性能力等特点,刚好完美解决了客户长期以来运维复杂.资源利用率不高.开发 ...

  9. iLogtail使用入门-iLogtail本地配置模式部署(For Kafka Flusher)

    ​简介:iLogtail使用入门-iLogtail本地配置模式部署(For Kafka Flusher). 阿里已经正式开源了可观测数据采集器iLogtail.作为阿里内部可观测数据采集的基础设施,i ...

  10. [DApp] Moralis 无服务架构方式构建 DApp

    Moralis 提供的使用功能包括三个方面: 进一步封装Web3功能的 Moralis SDK,极大方便了开发者对于DApp基础功能的开发,比如 MetaMask登录验证,签名,IPFS集成,DApp ...