今年的WWDC2019上最使人激動的新技術無疑就是全新的UI框架SwiftUI了。對於蘋果開發者來講,它爲你們開啓了一個美麗的新世界:git
SwiftUI着實驚豔,但遺憾的是它要求iOS 13.0以上的系統。這一條約束讓你們以爲它還很遙遠,由於國內多數App還要適配iOS 9.0,甚至iOS 8.0。github
其實,SwiftUI的核心在於聲明式語法描述界面,而聲明式語法並非什麼新鮮事物,著名的React和近來大熱的Flutter都採用了聲明式語法。筆者查找和比較了一些開源的聲明式界面框架,但願找到一個SwiftUI的合適替補,讓你們在本身現有的項目裏也能擁有相似SwiftUI的開發體驗。編程
Layout
國外大神出品,基於自定義的XML DSL語法,功能強大,完備,支持Live Reload,自帶工具集。swift
TemplateKit
類React框架,基於自定義的XML DSL語法,支持Live Reload。數組
LayoutKit
LinkedIn出品,質量性能放心。bash
ComponentKit
Facebook出品,使用Objective-C++編寫,異步高性能佈局,支持組件回收重用,優化內存和滑動性能。閉包
Render
類React框架,支持組件回收重用,優化內存和滑動性能。框架
Tokamak
類React框架。異步
Komponents 類React框架,聲明式語法比較簡潔,與SwiftUI較爲接近。工具
Few
類React框架。
Lima
超輕量級的框架,語法上與SwiftUI最爲接近。
這些框架都是在蘋果發佈SwiftUI以前誕生的。比較完一圈之後,我不禁得感嘆,仍是SwiftUI更優雅,更強大。這也不難理解,畢竟蘋果是後來者,SwiftUI是汲取了業界最新理念,厚積薄發的超越之做。
至於哪一個框架更值得推薦,我想應該是因人而異。熟悉React的朋友,能夠選擇類React框架;看重性能的朋友,能夠選擇兩個大廠的框架;須要實時預覽開發體驗的朋友,能夠考慮前兩個框架。而從我我的來講,我選擇『小而美』的Lima。
它的優點以下:
咱們來作個比較,看下Lima和SwiftUI實現下面的界面,它們的代碼各長得什麼樣:
SwiftUI
HStack {
VStack {
Text("★★★★★")
Text("5 stars")
}
VStack {
HStack {
Text("Avocado Toast").font(.title)
Spacer()
Image("20x20_avocado")
}
Text("Ingredients: Avocado, Almond Butter, Bread, Red Pepper Flakes").lineLimit(1)
}
}
複製代碼
Lima
LMRowView(spacing: 10,
LMColumnView(
UILabel(text: "★★★★★", textAlignment: .center),
UILabel(text: "5 stars", textAlignment: .center)
),
LMColumnView(
LMRowView(
UILabel(text: "Avocado Toast", font:.preferredFont(forTextStyle: .title1)),
LMSpacer(),
UIImageView(image: UIImage(named: "20x20_avocado"))
),
UILabel(text: "Ingredients: Avocado, Almond Butter, Bread, Red Pepper Flakes")
)
)
複製代碼
看起來是否是很像,並且仍是咱們熟悉的UIKit,簡直完美了。
建議不要經過pod集成Lima,由於podspec上的Swift version和Deployment Target並不許確。實際上它的適用性是挺普遍的,能夠支持iOS 9.0以上系統,稍做修改,也能支持iOS 8.x。並且Swift 4.x和Swift 5.x均可以編譯經過。 另外,因爲源碼裏有Objective-C的代碼,因此純Swift的項目最好是集成編譯好的Lima.framework。
經過上面的例子咱們也看到,Lima自己很簡單,很容易上手。這點和Masonry很像,你甚至無需預先學習AutoLayout,只是經過看幾個例子就能夠開始使用Masonry了。Lima也是如此一目瞭然,你也無需去學習SwiftUI,花兩個小時看一下項目首頁上的那個說明文檔,跑一下Demo,基本就能開始編碼了。
這裏,我給你們簡單理一下Lima的源碼。
Lima是對UIKit的封裝,內部經過AutoLayout實現佈局。
LMLayoutView
和LMBoxView
是容器類的抽象基類,並不直接調用。
LMRowView
,LMColumnView
,LMAnchorView
,LMRootView
是四個容器類。
LMRowView
是水平容器;LMColumnView
是垂直容器;LMAnchorView
用於將子視圖排布在它的邊緣;LMRootView
一般用於控制器的根視圖,繞過系統定義的視圖Margins。LMSpacer
默認是當作空白,同時也能夠當作分隔線。
LMSpacer(height: 0.5, backgroundColor: UIColor.gray)
複製代碼
LMScrollView
,LMTableViewCell
,LMTableViewHeaderFooterView
,LMCollectionViewCell
是UIKit相應類型的子類。它們都有一個content屬性,用於接收內容視圖,並且它們的大小自動由content視圖決定。
對於經常使用的UIKit控件和上述Lima定義的類型,Lima都在擴展中給它們定義了便利構造器,咱們在聲明式語法中須要經過這些構造器聲明控件。
每一個構造器的最後一個參數(with)都是一個參數爲自身的閉包。這讓咱們能夠在尾隨閉包裏獲取控件的實例,並設置更多的屬性。
var detailView: LMColumnView!
LMColumnView(margin: 8, verticalAlignment: .top, spacing: 0) {
self.detailView = $0
$0.clipsToBounds = true
}
複製代碼
除了構造器,咱們還須要關注頭文件裏定義的屬性。視圖的排布是經過設置這些屬性實現的。
建議有興趣嘗試Lima的朋友,使用筆者fork的源碼。
我這份源碼修改了一個可能的同名屬性覆蓋問題,而且對原始代碼作了一些擴展。
Lima在UIView的分類裏定義了width和height屬性。這兩個屬性名很容易致使同名屬性覆蓋的問題。咱們經常使用的YYKit裏就定義了這兩個屬性。因此,我給這兩個屬性加了lm_前綴。
我給LMColumnView
, LMRowView
和 LMAnchorView
加了一個能夠接收子視圖數組的構造器,這樣能夠實現以下的調用:
let items = ["First", "Second", "Third", "Four", "Five"]
LMColumnView(
items.map { item in
UILabel(text: "Hello, \(item)!", textAlignment: .center)
}
)
複製代碼
我給UIButton
和 UITextField
的構造器里加入了事件處理參數,方便調用:
UIButton(title: "Press Me!", action: { [weak self] btn in
self?.showGreeting()
})
複製代碼
我添加了一個LMTableView
類,指望實現SwiftUI裏簡單的List效果。
SwiftUI
List(landmarks) { landmark in
HStack {
Image(landmark.thumbnail)
Text(landmark.name)
Spacer()
if landmark.isFavorite {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
}
}
}
複製代碼
Lima
LMTableView(items, { item in
LMTableViewCell(
LMRowView(
UILabel(text: "Hello, \(item)!"),
LMSpacer(),
UIImageView(image: UIImage(named: "EmailIcon")) {
if item == "Five" {
$0.isDisplayable = false
} else {
$0.isDisplayable = true
}
}
)
)
})
複製代碼
不過,個人實現Cell沒有作到重用,只適用於短列表。也歡迎你們繼續研究。
Lima用簡單的代碼實現了接近SwiftUI的簡潔的聲明式語法。可是,它只能看作是一個簡化版的SwiftUI,遠沒有SwiftUI強大。
SwiftUI很強大,很美麗,可是咱們還用不起來它。因此,筆者但願找一個開源的聲明式UI框架,在現有的項目裏引入聲明式編程。筆者找到了Lima,並擴展了它。若是,你如今正在用Masonry佈局UI,我建議您不妨試試Lima,由於聲明式UI是將來的趨勢,並且Lima和Masonry同樣簡單易用,Lima比Masonry的代碼更加簡潔易讀。