2019年WWDC大會上,蘋果在壓軸環(huán)節(jié)向大眾宣布了基于Swift語言構(gòu)建的全新UI框架——SwiftUI,開發(fā)者可通過它快速為所有的Apple平臺創(chuàng)建美觀、動態(tài)的應用程序。推薦大量使用struct代替類。
SwiftUI 就是?種聲明式的構(gòu)建界面的用戶接口工具包。
SwiftUI使用聲明式的語法構(gòu)建UI,我們只需要向系統(tǒng)聲明UI的View樣式,以及View如何轉(zhuǎn)換狀態(tài),其他的過程都交給系統(tǒng)去處理。
SwiftUI的界面不再像UIKit那樣,用ViewController 承載各種UIVew控件,而是一切皆View,所以可以把View切分成各種細致化的組件,然后通過組合的方式拼裝成最終的界面,這種視圖的拼裝方式提高了界面開發(fā)的靈活性和復用性。因此,視圖組件化是SwiftUI很大的亮點。
SwiftUI是聲明式的構(gòu)建方式,我們只需要聲明好界面系統(tǒng)會自動轉(zhuǎn)換狀態(tài),搭建界面更加的簡單
聲明式語法和指令式語法的區(qū)別:
聲明式的我們需要提前聲明好每個view的各種狀態(tài),以及狀態(tài)轉(zhuǎn)變的條件。后續(xù)界面和用戶在互動時,系統(tǒng)會幫我們自動進行狀態(tài)切換。
指令式的我們需要給每個view先設置好默認狀態(tài),后續(xù)界面和用戶在互動時,需要通過指令不停的去轉(zhuǎn)變view的狀態(tài)
因此聲明式的UI是提前聲明好各種狀態(tài),系統(tǒng)會自動幫我們進行狀態(tài)切換。指令式的UI是通過我們設定的指令來轉(zhuǎn)換狀態(tài)
比如界面調(diào)整、用戶交互、機型適配,UIKit都需要手動調(diào)整view,對于SwiftUI我們只需要聲明好我們想要的樣式,系統(tǒng)會幫我們?nèi)フ{(diào)整view。
可以這么說,SwiftUI相比于UIKit更加的抽象化了
統(tǒng)一蘋果終端
在 SwiftUI 出現(xiàn)之前,蘋果不同的設備之前的開發(fā)框架并不互通,增加開發(fā)者所需消耗的時間精力,也不利于構(gòu)建跨平臺的軟件體驗
SwiftUI具有了跨平臺性,蘋果的平臺都可以使用,iOS、macOS、tvOS、watchOS
降低界面開發(fā)難度
UIKit 的基本思想要求ViewController 承擔絕?部分職責,它需要協(xié)調(diào) model,view 以及??交互。這帶來了巨?的sideeffect 以及?量的狀態(tài)
SwiftUI是聲明式的構(gòu)建方式,我們只需要聲明好界面系統(tǒng)會自動轉(zhuǎn)換狀態(tài),搭建界面更加的簡單
更加高效
默認使用Metal渲染,性能非常高,比UIKit要好
更扁平化的內(nèi)聯(lián)數(shù)據(jù)結(jié)構(gòu)去分配內(nèi)存,值類型。占用內(nèi)存很少(所以在輕應用的開發(fā)更適合使用SwiftUI)
代碼量相比UIKit要更少,效率更高
更好的配合Swift語言
SwiftUI 使用了大量 Swift 的語言特性
聲明式語法
與UIKit布局相比,更加的抽象化,只需要向系統(tǒng)聲明界面樣式以及樣式變化條件,其他的系統(tǒng)會幫我們實現(xiàn),不需要我們自己去調(diào)整視圖
鏈式調(diào)用屬性
鏈式調(diào)用是 Swift 語言的一種特性,就是使用函數(shù)式編程,可以像鏈條那樣不斷地調(diào)用函數(shù),中間不需要斷開。使用這種方式可以大大減少代碼量。
除了系統(tǒng)提供的屬性可以使用之外,開發(fā)者也可以進行自定義
例如將不同字體、字號、行間距、顏色等屬性統(tǒng)合起來,可以組合成為一個叫「標題」的文字屬性。之后凡是需要將某一行文字設置成標題,直接添加這個自定義的屬性即可,使用這種方式進行開發(fā)無疑能夠極大的避免無意義的重復工作,更快的搭建應用界面框架。
界面元素的組件化
UIKit耦合了很多的操作邏輯,很難進行移植,更遑論組件化了
而SwiftUI僅僅聲明界面樣式,所以是可以將復雜視圖的拆分出來組件化
甚至還可以在其他平臺使用,以此跨平臺
一般我個人會將視圖組件區(qū)分為基礎組件、布局組件和功能組件
與UIKit互相兼容
把 UIKit 中已有的部分進行封裝,提供給 SwiftUI 使用。開發(fā)者需要做的僅僅是遵循UIViewRepresentable協(xié)議即可
并且在已有的項目中,也可以僅用 SwiftUI 制作一部分的 UI 界面
兩種代碼的風格是截然不同的,但在使用上卻基本沒有性能的損失。在最終的運行效果上,用戶也無法分辨出兩種界面框架的不同。
真實數(shù)據(jù)源(Source of truth)(重點)
SwiftUI中的數(shù)據(jù)源一定會是真實的,也就是準確的
在OC中,一個view的狀態(tài)由多種因素導致的,不同的來源,不同的邏輯操作(因此需要考慮及時更新界面)
因此在Swift中,提供了單一數(shù)據(jù)源的說法
只要在屬性聲明時加上 @State 等關鍵詞,就可以將該屬性和界面元素聯(lián)系起來,在每次數(shù)據(jù)改動后,都有機會決定是否更新視圖。
系統(tǒng)將所有的屬性都集中到一起進行管理和計算,也不再需要手寫刷新的邏輯。
因為在 SwiftUI 中,頁面渲染前會將開發(fā)者描述的界面狀態(tài)儲存為結(jié)構(gòu)體,更新界面就是將之前狀態(tài)的結(jié)構(gòu)體銷毀,然后生成新的狀態(tài)。
而在繪制界面的過程中,會自動比較視圖中各個屬性是否有變化,如果發(fā)生變化,便會更新對應的視圖,避免全局繪制和資源浪費。
使用這種方式,讀和寫都集中在一處,開發(fā)者就能夠更好地設計數(shù)據(jù)結(jié)構(gòu),比較方便的增減類型和排查問題。而不用再考慮線程、原子狀態(tài)、尋找最新數(shù)據(jù)等各種細節(jié),再決定通知相關的界面進行刷新。
UIKit 的基本思想要求ViewController 承擔絕?部分職責,它需要協(xié)調(diào) model,view 以及??交互。這帶來了巨?的sideeffect 以及?量的狀態(tài)
SwiftUI不僅為Apple的平臺帶來了一種新的構(gòu)建UI的方式,還有全新的Swift編碼風格;
可以推斷出:SwiftUI會出現(xiàn)很多組件庫,方便前端開發(fā);
支持熱更新,這一點可能讓更多的開發(fā)者擁抱SwiftUI;
雖然SwiftUI優(yōu)點很多,但是其使用的門檻很高,只能在iOS 13以上的系統(tǒng)使用;僅這點,很多公司和開發(fā)者望而卻步,目前主流應用最低支持iOS 9,至少3年之內(nèi),SwiftUI只能作為一個理論的知識儲備,所以其還有很長的路要走;
說了它的優(yōu)點,再說下它的缺點:
1.由于大量Struct來實現(xiàn)頁面,甚至事件處理也寫在Struct里面。要知道在Struct里是無法打印日志,這樣造成無法建立強大的日志跟蹤功能。一個好的軟件一定要一個強大的日志跟蹤系統(tǒng)。上次我開啟了蘋果的iOS內(nèi)存日志功能,發(fā)現(xiàn)兩個頁面切換一次打印的日志就達到50兆–100兆的日志。可見蘋果的內(nèi)存管理好,是靠多少人的不斷努力和打印跟蹤內(nèi)存分配和使用,只是對我們應用層開發(fā)者屏蔽了大量底層細節(jié)。自己的方便是建立在他人辛苦上的,沒有無緣無故的方便。
2.由于大量Struct來實現(xiàn)頁面,它沒有deinit(類似oc的dealloc函數(shù))。這樣造成無法跟蹤頁面和view等的內(nèi)存釋放跟蹤,定位是否有內(nèi)存泄漏。無法使用采用hook技術的MLeaksFinder庫檢查是否內(nèi)存泄漏。當然部分Struct可以用final class代替,但是和它提倡的采用Struc減少內(nèi)存相悖。實際上采用SwiftUI大都采用Struct
3.由于大量Struct來實現(xiàn)頁面,閃退時無法打印出頁面的類名,日志跟蹤時也顯示不出頁面的類名。點擊UI View Hierarchy,打印的頁面View是看不懂的內(nèi)容,如:TtGC7SwiftUI14_UIHostingViewVS_7AnyView: 0x109d12880。不是正確的類名。并且頁面層級稍微多兩層,點擊UI View Hierarchy就可能出不出來UI View Hierarchy了。這很不利于我們定位當前頁面是那個類。
看到無法打印當前在那個頁面的view,無法根據(jù)打印內(nèi)存在工程中搜索到對應的view,不利于熟悉代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-535336.html
這個是開啟僵尸進程后看到的閃退日志,可以看到無法看到那個類閃退了。
這個是oc的頁面層級結(jié)構(gòu),可以看到各個組件層級很清晰,頁面類名顯示的很清晰,一個不熟悉代碼的人很容易找到對應頁面類,找到對應頁面,很容易熟悉代碼。
4.由于SwiftUI采用的是盒子的設計概念。手機加載時由于內(nèi)存問題,通常用表格實現(xiàn)下拉內(nèi)容多的頁面,采用表格復用減少內(nèi)存加載。而SwiftUI在用VStack實現(xiàn)下拉時可能遇到上下滑動時,頁面元素亂飛的不可思議場景。不知道如何解決。文章來源地址http://www.zghlxwxcb.cn/news/detail-535336.html
struct ChannelSingleView: View {
@EnvironmentObject var server: ServerManager
@EnvironmentObject var geoHallModel: GeoHallViewModel
@EnvironmentObject var messageViewModel: MessagePageViewModel
var channel: ServerResponse.ChannelModel
var idx: Int
var angle: Double {
if let id = channel.id {
return geoHallModel.channelAngleDict[id] ?? 0.0
}
return 0.0
}
private var isSelected: Bool {
return channel.id == geoHallModel.currChannel?.id
}
var body: some View {
VStack(alignment: .center, spacing: 0) {
channelAvatar
.rotation3DEffect(.degrees(angle), axis: (x: 0, y: 1, z: 0.2))
if let name = channel.name {
Text(name)
.styleText(.size12, .black)
}
}
.frame(width: 51 * .pointRatio)
.overlay {
Color.bgcGray.opacity(isSelected ? 0 : 0.7)
}
.animation(.default, value: channel.top)
.id(channel.id)
.onTapGesture {
if !isSelected {
let canChangeTab = CustomTempVars.shared.canChangeTab
if canChangeTab {
CustomTempVars.shared.canChangeTab = false
Task {
var channel = channel
channel.roomID = await server.getChannelRoom(channel.id ?? "")
geoHallModel.switchChannel(channel)
}
withAnimation(.interpolatingSpring(stiffness: 20, damping: 5)) {
if let id = channel.id {
geoHallModel.channelAngleDict[id]! += 360
}
}
}
}
geoHallModel.clearReadDot(channel)
}
.ignoresSafeArea()
.padding(.trailing, .size05)
.padding(.leading, .size05)
// .padding(.trailing, 9 * .pointRatio)
.padding(.top, .safeAreaTop + .size05)
.padding(.bottom, .size05)
// .padding(.leading, 9 * .pointRatio)
}
}
有的頁面存在向下滑后或向上滑動頁面元素亂跳的一種場景
5.因為SwiftUI是一切皆view,大量使用Struct,當實現(xiàn)所有頁面默認失敗頁面和無數(shù)據(jù)時,oc是采用ViewController基類快速實現(xiàn),不知道SwiftUI實現(xiàn)。
6.當頁面發(fā)送網(wǎng)絡請求時,一般需要一個蒙層和動畫,防止用戶重復觸發(fā)請求導致各種異常。oc是采用第三方控件在keywindow加入蒙層和動畫的方式實現(xiàn)。SwiftUI可能有,我是不知道。這就是需要技術棧的積累問題。
7.當A頁面進入B頁面,B頁面查詢數(shù)據(jù)時,報錯需要彈出toast彈窗,并退出B頁面到A頁面。一般toast彈窗是現(xiàn)實在keywindow上的,但是kewindow是B頁面,而由于自動返回A頁面,B頁面銷毀了,就看不到這個toast彈窗了。使用MBProgressHUD時就會遇到該問題。有的app為了解決這個問題人為延遲推出B頁面,這樣降低用戶的體驗流暢度,不完美。另一用采用SVProgressHUD來實現(xiàn),它是異步時彈窗,顯示調(diào)用彈窗和實際顯示彈窗有一個時間差,正好在B頁面調(diào)用彈窗,在回到A頁面時,彈窗出來,所以能顯示出來。我們遇到過一個問題,一個請求后臺在時機毫秒內(nèi)返回,蒙層彈窗還沒有出來請求回來了,并且取消彈窗,實際上SVProgressHUD還沒有出來,導致后面沒有取消處理了,一直在哪里轉(zhuǎn)圈了。最佳解決方案是創(chuàng)建一個優(yōu)先級高于當前級別的window顯示蒙層和動畫。不知道SwiftUI處理這些細節(jié)問題。
8.SwiftUI提倡view組件化,可能產(chǎn)生view處理過多,不利于專類做專門的事情的原則。要平衡view的復雜性和復用性,不推薦過度的復用。
一個完美的產(chǎn)品不是完成基本功就完事,要完美處理各種細節(jié)。SwiftUI在技術棧積累不夠和各種組件前不建議實際應用。作為知識儲備是必要,立即實施風險太大,沒有必要。我們很欣賞SwiftUI簡潔性和快速開發(fā),很多細節(jié)需要我們解決。方便和功能強大是相悖的。正如java和C/C++的關系。使用java基本不關注指針使用和內(nèi)存使用,方便好學。C/C++需要處理煩人的指針和內(nèi)存使用問題,正因為它更接近底層,所以能實現(xiàn)java實現(xiàn)不了的問題和響應比java快30%。一個好的軟件不取決于采用那種語言,而是取決于開發(fā)軟件的人。SwiftUI還任重道遠,不要過于追求新技術。
由于Struct內(nèi)不能直接打印日志和立體圖是亂碼決定了SwiftUI是一個錯誤的產(chǎn)品,基本上相當于以前的storyboard。只是相當于以前直接拖入控件變成代碼實現(xiàn)UI。一個好的軟件缺少不了強大的日志系統(tǒng),只靠接口和效果,單步跟蹤,沒有日志的軟件,很難保證軟件質(zhì)量,更無法維護。我在很多公司見到許多app直接從來不打印日志,真不知道他們怎么開發(fā)出app的,這樣的app質(zhì)量可想而知,后期維護簡直是噩夢。SwiftUI是一切皆view,大量使用Struct基本上是從設計上摒棄日志,真不知道設計他的人是聰明還是傻!為了節(jié)省一點內(nèi)存,而放棄可維護性,得不償失。以前全使用storyboard和xid的人有多少,用代碼實現(xiàn)ui的又有多少?,F(xiàn)在又換成這樣不能打印日志和立體圖的SwiftUI,簡直是技術退步。Swift語言是語言的進步,他是強類型的語言,會自動約束程序員的語法錯誤。而object c是弱類型的語言,很多語法錯誤不檢查,過于啰嗦,全靠程序員的嚴謹性和代碼質(zhì)量。弱類型也存在優(yōu)點:在高質(zhì)量的程序員手里靈活性很好。就像c語言和c++語言的進步一樣。c++在某些應用中無法代替c 語言。新公司員工沒有大公司的架構(gòu)建議采用swfit開發(fā),不建議采用SwiftUI技術,采用代碼實現(xiàn)ui就可以。若是大公司對質(zhì)量控制很好,有很好的object c的mvvm架構(gòu),建議采用mvvm架構(gòu)。不建議為了追求新技術放棄優(yōu)秀的object c的mvvm架構(gòu)(帶app網(wǎng)關,ReactiveObjC,頁面路由)。咨詢過許多大廠的框架,他們?nèi)耘f采用object c語言開發(fā)的居多,采用mvvm架構(gòu)(帶app網(wǎng)關,ReactiveObjC,頁面路由)。swfit比object c語言更先進,但是限制也更多。好的軟件,主要取決于開發(fā)軟件的人和框架,而不取決語言本身。不是使用的先進的語言開發(fā)的軟件就好。有人說大廠很多都是網(wǎng)頁,開發(fā)的軟件太多,無法轉(zhuǎn)swfit。這樣是一方面的原因,但是不是全部。主要是大廠的框架足夠優(yōu)秀,代碼質(zhì)量要求嚴格,靈活性好。不要認為SwiftUI有Swift這幾個字就認為它是Swift更高級的形式,其實他只相當于原來的storyboard,是控制器和view的組合體。我不推薦使用SwiftUI。使用SwiftUI還是使用object c取決公司的技術積累,是否有十分好的架構(gòu)。若是啥架構(gòu)都沒有,建議采用Swift;若有很好的大公司object c建構(gòu),建議采用object c架構(gòu)。再次說不要采用SwiftUI技術。
到了這里,關于SwiftUI的優(yōu)缺點的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!