系统: Mac OS 10.15.1, XCode 11.2.1,swift 5.0
写作时间:2019-11-22

说明

Swift 5以后 ABI 稳定了。(参考: ABI Stability and More 和 Evolving Swift On Apple Platforms After ABI Stability )

什么是 ABI 稳定?

就是 binary 接口稳定,也就是在运行的时候只要是用 Swift 5 (或以上) 的编译器编译出来的 binary,就可以跑在任意的 Swift 5 (或以上) 的 runtime 上。这样,我们就不需要像以往那样在 app 里放一个 Swift runtime 了,Apple 会把它弄到 iOS 和 macOS 系统里。

app 尺寸会变小?

是的,但是这是 Apple 通过 App Thinning 帮我们完成的,不需要你操心。在提交 app 时,Apple 将会按照 iOS 系统创建不同的下载包。对于 iOS 12.2 的系统,因为它们预装了 Swift 5 的 runtime,所以不再需要 Swift 的库,它们会被从 app bundle 中删掉。对于 iOS 12.2 以下的系统,外甥打灯笼,照旧。

一个新创建的空 app,针对 iOS 12.2 打包出来压缩后的下载大小是 26KB,而对 iOS 12.0 则是 2.4MB。如果你使用了很多标准库里的东西,那这个差距会更大 (因为没有用到的标准库的符号会被 strip 掉),对于一个比较有规模的 app 来说,一般可以减小 10M 左右的体积。

还有什么其他好处么?

因为系统集成了 Swift,所以大家都用同一个 Swift 了,app 启动的时候也就不需要额外加载 Swift,所以在新系统上会更快更省内存。当然啦,只是针对新系统。

ABI稳定后Apple憋了个一统江湖的新框架SwiftUI.

  1. 这个框架相当简洁,拖拽控件跟写代码实现达到一致性,不需要额外的关联(去掉了@IBAction, @IBOutlet).
  2. 写一套代码在Apple所有产品通用(iPhone, iPad, AppleWatch, AppleTV).
  3. 可见即可得,写完代码,点击右边的Resume按钮,或者用快捷键command+option+p, 就可以看到运行起来的样子。
  4. 模拟运行:如果点击右下角的预览按钮,跟模拟器运行的效果是一样的。

下面就从0开始,打造上面的效果的例子。
实战的例子来源于:SwiftUI: Getting Started

创建工程

创建Xcode project (Shift-Command-N), 选择 iOS ▸ Single View App, 名字叫RGBullsEye, User Interface选择 SwiftUI。

SwiftUI是怎么启动的

打开分组RGBullsEye,将看到: 以前的AppDelegate.swift,现在分为AppDelegate.swiftSceneDelegate.swiftSceneDelegatewindow设置:

SceneDelegate 没有明确配置SwiftUI, 但是下面代码有:

let contentView = ContentView()// Use a UIHostingController as window root view controller.
// ...window.rootViewController = UIHostingController(rootView: contentView)
// ...

当app启动, window显示实例ContentView, 它定义在文件ContentView.swift. 它是一个结构体struct遵循协议View protocol(老逻辑是View对象):

struct ContentView: View {var body: some View {Text("Hello World")}
}

SwiftUI 定义了ContentViewbodybody包含了一个Text view 显示文字Hello World.

预览结构体ContentView_Previews 生产一个view包含了ContentView实例.

struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}

如何显示预览效果?点击右边视图的Resume按钮

预览如下:

如果没有看到Resume按钮,选择editor options, 选择Canvas,或者快捷键command+option+enter

编写UI占位结构

Text("Hello World") 替换为如下:

Text("Target Color Block")

点击Resume按钮,看看文字是否已经改变。

Command+点击在右侧预览界面的Text view, 选择 Embed in HStack:

看到左侧代码已经更新(实际上手动写代码,点击Resume视图也跟着更新)

HStack {Text("Target Color Block")
}

拷贝粘贴Text 代码, 更新HStack 如下.

HStack {Text("Target Color Block")Text("Guess Color Block")
}

发现不需要逗号,效果是两个Text View在同一行:
Notice you don’t separate the two statements with a comma — just write each on its own line:

准备添加滑动块视图,在横向容器HStack里加入纵向容器VStack. — 在代码里Command-点击HStack, 选择Embed in VStack:

HStack闭包下面换行,点击右上角**+**按钮,打开控件库Library, 拖拽一个Vertical Stack 在换行的位置:
添加Text View代码如下,预览如下:

完成以上UI布局,代码如下。(实际上,直接写代码就好,跟拖拽控件一样的效果)

VStack {HStack {Text("Target Color Block")Text("Guess Color Block")}Text("Hit me button")VStack {Text("Red slider")Text("Green slider")Text("Blue slider")}
}

在横向容器里,添加两个纵向容器VStack, 里面都有长方形Rectangle。 左边的纵向容器表示目标颜色,右边的纵向容器表示用户可以改变的颜色。

HStack {// Target color blockVStack {Rectangle()Text("Match this color")}// Guess color blockVStack {Rectangle()HStack {Text("R: xxx")Text("G: xxx")Text("B: xxx")}}
}

@State修饰属性

@State修饰的属性,表示属性更新,界面也同步更新。
在结构体ContentView里面,在body闭包的上面添加如下属性:

let rTarget = Double.random(in: 0..<1)
let gTarget = Double.random(in: 0..<1)
let bTarget = Double.random(in: 0..<1)
@State var rGuess: Double
@State var gGuess: Double
@State var bGuess: Double

R, G, B 的值在区间[0,1). 初始化target的值. 需要初始化Guess的值为0.5.

向下滚动到结构体ContentView_Previews, 实例化ContentView 需要改为带参数,修改如下:

ContentView(rGuess: 0.5, gGuess: 0.5, bGuess: 0.5)

同样需要修改在类SceneDelegate, 的方法scene(_:willConnectTo:options:) — 替换 ContentView()为:

let contentView = ContentView(rGuess: 0.5, gGuess: 0.5, bGuess: 0.5)

给目标矩形添加颜色

Rectangle().foregroundColor(Color(red: rTarget, green: gTarget, blue: bTarget, opacity: 1.0))

给猜测矩形添加颜色

Rectangle().foregroundColor(Color(red: rGuess, green: gGuess, blue: bGuess, opacity: 1.0))

点击Resume按钮预览如下:

滑块控件复用View

在没有重用之前, 在滑块在VStack, 替换代码 Text("Red slider") 如下:

HStack {Text("0").foregroundColor(.red)Slider(value: $rGuess)Text("255").foregroundColor(.red)
}
  1. 更新Text views的颜色为红色. 初始化滑块的值(0.5) . 滑块的值范围为[0, 1].
  2. $修饰变量rGuess,表示可读可写绑定 — 当修改滑块的值的时候,需要同步更新猜测矩形的颜色.

为了看出是否用修饰符$的区别,把如下代码添加到猜测矩形的下面

HStack {Text("R: \(Int(rGuess * 255.0))")Text("G: \(Int(gGuess * 255.0))")Text("B: \(Int(bGuess * 255.0))")
}

预览效果如下:

上面的滑块有点挤,添加一点空间,用.padding() 如下

HStack {Text("0").foregroundColor(.red)Slider(value: $rGuess)Text("255").foregroundColor(.red)
}.padding()

预览效果会宽一些

上面实现了红色滑块,实际上绿色、蓝色模块都是相同的逻辑,这里就要重构为公用方法。

Command-点击 红色滑块的HStack, 选择 Extract Subview:

右键Refactor ▸ Extract to Function一样可以达到上面重构的效果.
ExtractedView命名为ColorSlider, 在body闭包的上面添加代码:

@Binding var value: Double
var textColor: Color

替换 $rGuess$value, 替换 .redtextColor:

Text("0").foregroundColor(textColor)
Slider(value: $value)
Text("255").foregroundColor(textColor)

回到VStack调用方法ColorSlider()的地方, 添加参数:

ColorSlider(value: $rGuess, textColor: .red)

就是上面

SwiftUI实战一:从入门到精通相关推荐

  1. python机器学习实战一:入门

    import requests r = requests.get(r"https://api.github.com/users/acombs/starred") r.json() ...

  2. [Python深度学习入门]实战一·Numpy梯度下降求最小值

    [深度学习入门]实战一·Numpy梯度下降求最小值 问题描述: 求解y1 = xx -2 x +3 + 0.01*(-1到1的随机值) 与 y2 = 0 的最小距离点(x,y) 给定x范围(0,3 不 ...

  3. 前端-Vue.js从入门到精通基础笔记(理论+实操+知识点速查)

    #[2022.3]尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查) 前言 本文完全基于 参考资料:加工整理而成,包括其代码,案例,资源等.前置知识是学习尚硅谷的视频教程,本文配合其教程 ...

  4. 视频教程-JSP从入门到精通2016+在线视频教学平台项目实训-其他

    JSP从入门到精通2016+在线视频教学平台项目实训 19年软件开发经验,设计开发40多个大型软件,10年从事高等教育,主要为java系列课程,带你轻松进入java生涯. 赖国荣 ¥68.00 立即订 ...

  5. 用Python和Pygame写游戏-从入门到精通(1)

    From: http://eyehere.net/2011/python-pygame-novice-professional-1/ 博客刚开,打算做一个Pygame的系列,翻译自Will McGug ...

  6. 视频教程-从入门到精通学全套AI 轻松掌握illustrator基础加实战技能视频课程-Illustrator

    从入门到精通学全套AI 轻松掌握illustrator基础加实战技能视频课程 中国电商服务联盟品牌讲师.中国国际互联网节品牌顾问. 12年视觉设计经验,5年视觉讲师经验.电商品牌视觉策划讲师 .曾任知 ...

  7. 从入门到精通学全套AI 轻松掌握illustrator基础加实战技能视频课程-王诚-专题视频课程...

    从入门到精通学全套AI 轻松掌握illustrator基础加实战技能视频课程-948人已学习 课程介绍         掌握全套AI基础课程,熟练掌握illustrator各项技巧. 基础教学加有趣有 ...

  8. 虚幻引擎5(UE5)实时VFX游戏特效制作入门到精通

    UE5 Niagara学习教程  课程获取:虚幻引擎5(UE5)实时VFX游戏特效制作入门到精通-云桥网 你会学到什么 我将通过创建各种各样的实时效果来教你虚幻引擎中强大的粒子系统. 我们将从简单的基 ...

  9. 它来了!ROS2从入门到精通:理论与实战

    ROS是什么? 随着人工智能技术的飞速发展与进步,机器人的智能化已经成为现代机器人发展的终极目标.机器人发展的速度在不断提升,应用范围也在不断拓展,例如自动驾驶.移动机器人.操作机器人.信息机器人等. ...

  10. 七夕福利 | 3D视觉从入门到精通系统学习教程

    写在前面 首先提前祝大家七夕快乐,感谢大家对工坊的陪伴与支持! 今天是七夕福利活动的最后一天,共100张券,已经送出去了60多张,还剩不到35张,大家可以抓住本次的活动机会,享受全年的最低价(优惠了7 ...

最新文章

  1. 父域与子域之的信任关系
  2. java.lang.NullPointerException 空指针异常问题
  3. javascript中==和===的区别
  4. 【离散数学】实验 编写一个简单的三人表决器
  5. CSRF 跨站请求伪造 为什么b网站请求a网站的地址能带上a网站的cookie
  6. mail 命令发送附件
  7. Springboot属性文件application.properties配置大全,版本:1.5.4
  8. 使用listen()和accept()函数
  9. BUUCTF--相册
  10. 基于SpringBoot的救援物资管理系统
  11. 用微信网页版阅读文章
  12. 夜深人静, 看看编程人生
  13. oracle的权限授予,oracle权限命令
  14. win7计算机图标排列,win7系统桌面图标排列顺序打乱的操作方法
  15. 淘宝商城:将公布和解条件
  16. Java中的switch
  17. 全国产!全志A40i+Logos FPGA核心板(4核ARM Cortex-A7)硬件说明
  18. html中的函数怎么显示变量,css - 原生变量及使用函数 var()
  19. 东方信息苑c语言,上海市东方社区信息苑一览表.PDF
  20. 计算机专业的相关英语词汇,计算机专业英语单词大全

热门文章

  1. python如何预测双色球信息_python预测下一期双色球号码【机器学习】
  2. linux pcie热插拔驱动_嵌入式Linux驱动离不开的知识:深入解析Linux Platform_device
  3. 户外lisp导向牌如何安装_他山之石可攻玉,赴成都、重庆学习考察户外广告和门头牌匾规划管理工作...
  4. java welcome-file_通过JSF项目中的welcome-file设置默认主页
  5. oracle 11g给表建触发器错误“索引中丢失 IN 或 OUT 参数:: 1
  6. asp.net 2.0中页的生存周期(Lifecycle)和动态控件[转]
  7. HTTP 连接管理进化论
  8. git 遇到fatal:multiple stage entries for merged file
  9. 备课好帮手,免费分享 下载
  10. vs多项目模板及add-in开发