Skip to content

Commit 5a22c2a

Browse files
committed
增加100 days of swiftui文章.
1 parent 616b69b commit 5a22c2a

File tree

9 files changed

+221
-0
lines changed

9 files changed

+221
-0
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
+++
2+
title = "100 Days of SwiftUI"
3+
date = 2024-04-09T19:04:00-07:00
4+
lastmod = 2024-04-09T22:16:43-07:00
5+
tags = ["swift", "swiftui", "ios"]
6+
categories = ["swift", "swiftui", "ios"]
7+
draft = false
8+
toc = true
9+
+++
10+
11+
## <span class="section-num">1</span> 缘起 {#缘起}
12+
13+
我花了半年多的时间,在工作之余的闲暇时间,学习了苹果的Swift语言和SwiftUI框架,想体现下IOS开发,再看下有没有机会通过写软件来做点副业。 <br/>
14+
15+
先花了大概3个月时间,通过 [The Swift Programming Language](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour/) 这本官方电子书[^fn:1]来学习Swift这门语言,又花了接近4个月的时候来学习 [100 Days of SwiftUI](https://www.hackingwithswift.com/100/swiftui) 这门课程[^fn:2],每天花费1到2小时来学习一课,总共100课,所以顾名思义叫 100 Days of SwiftUI. <br/>
16+
17+
每完成一课,就在Twitter上发一条推文,今天刚好把第100天的推文发了. <br/>
18+
19+
{{< figure src="/ox-hugo/tweet_day_100.png" >}} <br/>
20+
21+
{{< figure src="/ox-hugo/tweet_day_99.png" >}} <br/>
22+
23+
{{< figure src="/ox-hugo/tweet_day_96.png" >}} <br/>
24+
25+
今天是结课之日,我通过了结课的考试,总分100分,考了91分,喜提课程证书一枚. <br/>
26+
27+
{{< figure src="/ox-hugo/100_days_of_swiftui_certificate.jpg" >}} <br/>
28+
29+
并在整个课程中,写了19个IOS App, 源码也基本放在[ GitHub](https://github.com/ramsayleung?tab=repositories&q=&type=&language=swift&sort=)&nbsp;[^fn:3]上了,不过所有的App都没有上架App Store,因为我还没有给苹果交税(99美刀的注册费). <br/>
30+
31+
经过这100节课和19个APP的训练,我已经掌握了使用Swift和SwiftUI的基础开发技能,算是个入门的IOS开发了, 现在我可以说自己是前端,后端,数据开发,IOS开发都搞过的全栈(~~~~)工程师了(不是) <br/>
32+
33+
但是在苹果做出改变之前,我SwiftUI之旅可能就先到此为止了,原因下文再谈 <br/>
34+
35+
36+
## <span class="section-num">2</span> Swift 初体验 {#swift-初体验}
37+
38+
Swift 是由LLVM之父 [Chris Lattner](https://en.wikipedia.org/wiki/Chris_Lattner)&nbsp;[^fn:4]在2010开始开发,在2014年的WWDC苹果开发者大会被苹果正式推出的一门编程语言。 <br/>
39+
40+
按照官方的说法,Swift从Objective-C, Rust, Haskell, Ruby, Python, C# 都有不同程度的借鉴和学习。 <br/>
41+
42+
因为我对上面提到的语言多少有涉猎,所以学习Swift起来基本没有什么困难,=Optional=, `Error Handling`, `Result`, `Generic`, `Enumerations`, `Protocol` 这些概念都和Rust的大同小异。 <br/>
43+
44+
又因为是由LLVM之父来操刀,所以语言本身也设计得很优雅. <br/>
45+
46+
让我眼前一亮的可能是借鉴自 [C# Extension Methods](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods)&nbsp;[^fn:5]`extension` 功能 , 可以对已有的 class, enum 或者是 protocol 类型增加新的函数,也就是在不修改源码的情况下,扩展已有的功能. <br/>
47+
48+
例如,以下的代码就可以扩展内置的 `Double` 类型, 实现以米为单位,进行千米, 厘米,毫米,公尺的转换: <br/>
49+
50+
```swift
51+
extension Double {
52+
var km: Double { return self * 1_000.0 }
53+
var m: Double { return self }
54+
var cm: Double { return self / 100.0 }
55+
var mm: Double { return self / 1_000.0 }
56+
var ft: Double { return self / 3.28084 }
57+
}
58+
let oneInch = 25.4.mm
59+
print("One inch is \(oneInch) meters")
60+
// Prints "One inch is 0.0254 meters"
61+
let threeFeet = 3.ft
62+
print("Three feet is \(threeFeet) meters")
63+
// Prints "Three feet is 0.914399970739201 meters"
64+
```
65+
66+
总体而言, Swift是一门吸收了众多PL理论的现代编程语言 <br/>
67+
68+
69+
## <span class="section-num">3</span> SwiftUI {#swiftui}
70+
71+
SwiftUI 使用的声明式语法,让开发者写页面布局和效果变得简洁清晰, 例如通过 `VStack`, `HStack`, `ZStack` 就可以实现X轴,Y轴,和Z轴方向的布局 <br/>
72+
73+
例如下面这个就是通过 `ZStack` 几行代码实现的叠加效果: <br/>
74+
75+
```swift
76+
let colors: [Color] =
77+
[.red, .orange, .yellow, .green, .blue, .purple]
78+
79+
80+
var body: some View {
81+
ZStack {
82+
ForEach(0..<colors.count) {
83+
Rectangle()
84+
.fill(colors[$0])
85+
.frame(width: 100, height: 100)
86+
.offset(x: CGFloat($0) * 10.0,
87+
y: CGFloat($0) * 10.0)
88+
}
89+
}
90+
}
91+
```
92+
93+
{{< figure src="/ox-hugo/zstack_rectangle.png" >}} <br/>
94+
95+
除了声明式语法之外,SwiftUI让人赏心悦目的就是动画。好的动画在App里面绝对能起到画龙点睛的作用,而SwiftUI的内置动画已经非常强大了,下面就是使用内置动画实现的动画效果: <br/>
96+
97+
```swift
98+
struct ContentView: View {
99+
@State private var dragAmount = CGSize.zero
100+
@State private var enable = false
101+
let letters = "Hello, World"
102+
var body: some View{
103+
HStack(spacing: 0) {
104+
ForEach(0..<letters.count, id: \.self) { index in
105+
Text(String(letters[letters.index(letters.startIndex, offsetBy: index)]))
106+
.padding(5)
107+
.font(.title)
108+
.background(enable ? .green : .blue)
109+
.offset(dragAmount)
110+
.animation(.linear.delay(Double(index) / 20), value: dragAmount)
111+
}
112+
}.gesture(
113+
DragGesture()
114+
.onChanged {
115+
dragAmount = $0.translation
116+
}
117+
.onEnded { _ in
118+
dragAmount = CGSize.zero
119+
enable.toggle()
120+
}
121+
)
122+
}
123+
}
124+
```
125+
126+
{{< figure src="/ox-hugo/drag_animation.gif" >}} <br/>
127+
128+
```swift
129+
struct HeartBeatView: View {
130+
@State private var animationAmount = 1.0
131+
var body: some View {
132+
Button("SOS"){
133+
}
134+
.padding(50)
135+
.background(.red)
136+
.foregroundColor(.white)
137+
.clipShape(Circle())
138+
.overlay(
139+
Circle()
140+
.stroke(.red)
141+
.scaleEffect(animationAmount)
142+
.opacity(2 - animationAmount)
143+
.animation(.easeOut(duration: 1)
144+
.repeatForever(autoreverses: false), value: animationAmount)
145+
)
146+
.onAppear {
147+
animationAmount = 2
148+
}
149+
}
150+
}
151+
```
152+
153+
{{< figure src="/ox-hugo/hearbeat.gif" >}} <br/>
154+
155+
而Xcode 15新增的预览功能也很好用,可以让开发者不需要启动iPhone模拟器就能预览页面效果,节省了非常多的等待时间。 <br/>
156+
157+
{{< figure src="/ox-hugo/xcode_preview.png" >}} <br/>
158+
159+
160+
## <span class="section-num">4</span> 问题 {#问题}
161+
162+
听起来好像很美好, IDE新功能好用,编程语言优雅, UI框架简洁好用,但是苹果的开发思路却有大问题: 苹果开发的SwiftUI不向后兼容老版本的IOS。 <br/>
163+
164+
SwiftUI大部分功能都是只支持IOS16及以后的版本,而苹果新出来的数据持久框架 `SwiftData` 甚至只支持IOS17, <br/>
165+
更离谱的是,SwiftUI的BugFix 也只支持高版本IOS, 这就意味着用户不升级IOS版本,甚至SwiftUI的bug开发者都没法修复。 <br/>
166+
167+
不支持旧版本的IOS就让一大批的开发者和公司都没有动力去使用SwiftUI: <br/>
168+
169+
对于开发新应用的开发者而言,只支持IOS17就意味着会流失一大群使用IOS16及以下版本的用户, <br/>
170+
而对于拥有存量用户的公司而言,更没有动力去使用SwiftUI,用了之后,旧版本IOS的用户可能直接无法打开应用。 <br/>
171+
172+
因此SwiftUI就陷入了一个尴尬的境地,东西做得好,但是不会有人用; <br/>
173+
174+
没有人自然就不用有人分享,宣传这门技术,自然就导致相关的学习资料非常匮乏, 进一步加深了初学者的学习难度; <br/>
175+
176+
开发遇到问题连懂的人都不用,官方文档写了又约等于没有写, 直接劝退初学者,恶性循环。 <br/>
177+
178+
又因为接受SwiftUI的开发者还不多,苹果版本迭代起来更加肆无忌惮,新版本又引入一堆的Breaking change,导致开发者更新版本非常痛苦. <br/>
179+
180+
另外一个问题就是SwiftUI与苹果现有框架整合得不够好,如 `CoreImage` 框架,顾名思义是用来作图片处理. <br/>
181+
182+
但之前是使用Objective-C写的,直接使用SwiftUI来调用,就会变成相当恶心,需要把Swift的数据结构传换成Objective-C来处理, 如: <br/>
183+
184+
```swift
185+
func applyProcess(){
186+
guard let outputImage = currentFilter.outputImage else {return}
187+
guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else{return}
188+
let uiImage = UIImage(cgImage: cgImage)
189+
processedImage = Image(uiImage: uiImage)
190+
}
191+
192+
func loadImage() {
193+
Task{
194+
guard let imageData = try await selectedItem?.loadTransferable(type: Data.self) else {return}
195+
196+
guard let inputImage = UIImage(data: imageData) else {return}
197+
198+
let beginImage = CIImage(image: inputImage)
199+
currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
200+
applyProcess()
201+
}
202+
}
203+
```
204+
205+
`CoreImage` 框架的 `CIImage` 转成 `CoreGraphics` 框架的 `CGImage`, 然后再把 `CGImage` 转换成 `UIKit` 框架 `UIImage`, 然后再转换回SwiftUI 内置的 `Image` 类型, 可谓是相当麻烦了. <br/>
206+
207+
但是对比SwiftUI只支持高版本的问题,Objective-C和Swift的互操作问题也只能算是恶心,但是起码有解决方法,对于前者,开发者是完全没法自行解决. <br/>
208+
209+
210+
## <span class="section-num">5</span> 总结 {#总结}
211+
212+
过了一把野生IOS开发的瘾,但是除非是苹果愿意让SwiftUI支持低版本的IOS, <br/>
213+
不然我是不会继续使用SwiftUI来开发IOS了,受众太有限了,也没有太大的前景。 <br/>
214+
215+
想要支持低版本的IOS,就只能走UIKit和Objective-C这条历史老路,我对此着实是望而生畏,有空还是学习点其他有趣的东西。 <br/>
216+
217+
[^fn:1]: <https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour/> <br/>
218+
[^fn:2]: <https://www.hackingwithswift.com/100/swiftui> <br/>
219+
[^fn:3]: <https://github.com/ramsayleung?tab=repositories&q=&type=&language=swift&sort>= <br/>
220+
[^fn:4]: <https://en.wikipedia.org/wiki/Chris_Lattner> <br/>
221+
[^fn:5]: <https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods> <br/>
311 KB
Loading

static/ox-hugo/drag_animation.gif

296 KB
Loading

static/ox-hugo/hearbeat.gif

89.6 KB
Loading

static/ox-hugo/tweet_day_100.png

298 KB
Loading

static/ox-hugo/tweet_day_96.png

286 KB
Loading

static/ox-hugo/tweet_day_99.png

142 KB
Loading

static/ox-hugo/xcode_preview.png

168 KB
Loading
6.14 KB
Loading

0 commit comments

Comments
 (0)