開(kāi)始之前:請(qǐng)確保你的系統(tǒng)版本為macOS 10.15及以上版本且已經(jīng)安裝了Xcode 11寺滚。這種組合使您可以在Xcode內(nèi)部預(yù)覽SwiftUI設(shè)計(jì)荧缘,這比一直推送到模擬器的速度要快得多。
什么是SwiftUI志笼?
SwiftUI是一個(gè)用戶界面工具包汹忠,可讓我們以聲明的方式設(shè)計(jì)應(yīng)用程序疚宇。這是一種奇特的方式,我們告訴SwiftUI我們希望UI的展示效果和工作方式旭从,它知道如何在用戶與之交互時(shí)實(shí)現(xiàn)這一點(diǎn)稳强。
與命令式UI相比,聲明式UI最好理解和悦,這是iOS開(kāi)發(fā)人員在iOS 13之前所做的退疫。在命令式用戶界面中,我們可以使用戶在單擊按鈕時(shí)調(diào)用一個(gè)函數(shù)鸽素,并在函數(shù)內(nèi)部讀取一個(gè)值褒繁。并顯示標(biāo)簽-我們會(huì)根據(jù)正在發(fā)生的事情定期修改用戶界面的外觀和工作方式。
命令式UI會(huì)引起各種問(wèn)題馍忽,其中大多數(shù)問(wèn)題都圍繞state發(fā)生棒坏,這是另一個(gè)花哨的術(shù)語(yǔ)燕差,意為“我們存儲(chǔ)在代碼中的值”。我們需要跟蹤代碼處于什么狀態(tài)坝冕,并確保我們的用戶界面正確反映了該狀態(tài)徒探。
如果我們的一個(gè)屏幕具有一個(gè)會(huì)影響UI的布爾值屬性,則我們有兩種狀態(tài):布爾值可以打開(kāi)或關(guān)閉喂窟。如果我們有兩個(gè)布爾值A(chǔ)和B测暗,則現(xiàn)在有四個(gè)狀態(tài):
- A關(guān)閉,B關(guān)閉
- A打開(kāi)磨澡,B關(guān)閉
- A關(guān)閉碗啄,B打開(kāi)
- A打開(kāi),B打開(kāi)
如果我們有三個(gè)布爾值呢稳摄?五個(gè)呢稚字?或者多個(gè)整數(shù),字符串厦酬,日期等等胆描?好吧,那么我們要復(fù)雜得多弃锐。
如果你曾經(jīng)使用過(guò)一個(gè)應(yīng)用程序袄友,無(wú)論您嘗試多少次來(lái)告訴它自己已經(jīng)讀過(guò)該死的東西殿托,但它仍說(shuō)你有一條未讀的消息霹菊。這是一個(gè)狀態(tài)問(wèn)題–是命令式UI引起的問(wèn)題。
相比之下支竹,聲明性UI可以讓我們立即告知iOS應(yīng)用程序的所有可能狀態(tài)旋廷。我們可能會(huì)說(shuō),如果已登錄礼搁,則顯示歡迎消息饶碘,但如果已注銷(xiāo),則顯示登錄按鈕馒吴。我們不需要編寫(xiě)代碼來(lái)手動(dòng)在這兩個(gè)狀態(tài)之間移動(dòng)–這是難看的命令式工作方式扎运!
相反,當(dāng)狀態(tài)更改時(shí)饮戳,我們讓SwiftUI在用戶界面布局之間移動(dòng)豪治。我們已經(jīng)根據(jù)用戶登錄或注銷(xiāo)告訴了它要顯示的內(nèi)容,因此當(dāng)我們更改身份驗(yàn)證狀態(tài)時(shí)扯罐,SwiftUI可以代表我們更新UI负拟。
這就是聲明性的含義:我們不是要手動(dòng)顯示和隱藏SwiftUI組件,而是要告訴它要遵循的所有規(guī)則歹河,而讓SwiftUI確保這些規(guī)則得到強(qiáng)制執(zhí)行掩浙。
但是SwiftUI不僅止于此:它還充當(dāng)跨平臺(tái)的用戶界面層花吟,可跨iOS,macOS厨姚,tvOS甚至watchOS運(yùn)行衅澈。這意味著您現(xiàn)在可以學(xué)習(xí)一種語(yǔ)言和一種布局框架,然后將代碼部署到任何地方遣蚀。
SwiftUI vs Interface Builder和storyboards
全面更新了Xcode 11.2
每個(gè)經(jīng)驗(yàn)豐富的iOS開(kāi)發(fā)人員都熟悉Interface Builder和Storyboard矾麻,甚至XIB也是如此。他們可能不喜歡它們芭梯,但至少對(duì)它們熟悉险耀。如果您以前沒(méi)有使用過(guò)這些,你應(yīng)該跳過(guò)這一步玖喘。
還在這里甩牺?這意味著您以前使用過(guò)IB,并且可能會(huì)對(duì)SwiftUI的不同感到好奇累奈。
那么贬派,讓我問(wèn)您一個(gè)問(wèn)題:您是否曾經(jīng)手動(dòng)編輯storyboard或XIB?
可能沒(méi)有澎媒。好吧搞乏,除了這一次之外,大體上答案是否定的——storyboards和XIBs包含大量不易閱讀或編輯的XML戒努。
更糟糕的是请敦,storyboard有一個(gè)習(xí)慣是隨著時(shí)間的推移越來(lái)越大。當(dāng)然储玫,它們可能從很小的地方開(kāi)始侍筛,但是隨后您又添加了另一個(gè)視圖控制器和另一個(gè)視圖控制器,然后突然您意識(shí)到在一個(gè)文件中有十個(gè)屏幕的數(shù)據(jù)撒穷,你所做的任何源代碼管理更改都會(huì)突然變得非常痛苦匣椰。
但是,盡管單點(diǎn)故障并不好端礼,當(dāng)有人打開(kāi)帶有storyboard修改的拉取請(qǐng)求時(shí)禽笑,基本上不可能看到有什么變化,storyboards和XIBs還有一個(gè)更大的問(wèn)題蛤奥。
您會(huì)看到佳镜,Interface Builder對(duì)我們的Swift代碼不太了解,而我們的Swift代碼對(duì)Interface Builder也不太了解喻括。結(jié)果邀杏,我們最終得到了許多不安全的功能:我們使用Ctrl從IB拖動(dòng)到我們的代碼中,將某物連接到一個(gè)動(dòng)作,但是如果刪除該動(dòng)作望蜡,代碼仍然可以編譯——IB真的不介意它呼叫的代碼是否已經(jīng)不存在唤崭。
類(lèi)似地,當(dāng)我們從storyboard或表格視圖單元中創(chuàng)建視圖控制器時(shí)脖律,我們使用字符串來(lái)標(biāo)識(shí)代碼中的重要對(duì)象——一個(gè)如此普遍的系統(tǒng)谢肾,它甚至擁有自己的名稱(chēng):“字符串類(lèi)型的API”。即使這樣小泉,我們也需要使用類(lèi)型轉(zhuǎn)換芦疏,因?yàn)镾wift不能知道它返回的表視圖單元實(shí)際上是一個(gè)MooncakeTableViewCell。
存在這些問(wèn)題是因?yàn)镮B和Swift是很獨(dú)立的東西微姊。這并不是一個(gè)很大的驚喜——Interface Builder不僅可以追溯到最初MacOSX出現(xiàn)之前酸茴,而且它也是圍繞著Objective-C的工作方式而設(shè)計(jì)的。
SwiftUI在過(guò)去的基礎(chǔ)上取得了重大突破兢交。這是一個(gè)僅限Swift的框架薪捍,不是因?yàn)樘O(píng)果公司認(rèn)為Objective-C是時(shí)候死了,而是因?yàn)樗孲wiftUI充分利用了Swift的所有功能——值類(lèi)型配喳,隱式返回類(lèi)型酪穿,協(xié)議擴(kuò)展等等。
不管怎樣晴裹,我們將很快了解SwiftUI的工作原理被济。目前,您至少需要知道的是涧团,SwiftUI修復(fù)了人們使用舊的Swift + Interface Builder方法所遇到的許多問(wèn)題:
- 我們不必再爭(zhēng)論基于程序或storyboard的設(shè)計(jì)只磷,因?yàn)镾wiftUI同時(shí)為我們提供了這兩種設(shè)計(jì)。
- 在提交用戶界面工作時(shí)少欺,我們不再需要擔(dān)心創(chuàng)建源代碼控制問(wèn)題喳瓣,因?yàn)榇a比storyboard的XML更易于閱讀和管理馋贤。
- 我們不再需要為字符串類(lèi)型的API擔(dān)心太多了——雖然仍然有一些赞别,但數(shù)量大大減少了。
- 我們不再需要擔(dān)心不存在的調(diào)用函數(shù)配乓,因?yàn)槲覀兊挠脩艚缑嬉延蒘wift編譯器檢查仿滔。
因此,我希望您會(huì)同意犹芹,遷移到SwiftUI可以帶來(lái)很多好處崎页!
關(guān)于SwiftUI的常見(jiàn)問(wèn)題
學(xué)習(xí)哪個(gè):SwiftUI或UIKit?
在我問(wèn)過(guò)的所有SwiftUI問(wèn)題中腰埂,有一個(gè)比其他任何問(wèn)題都多:“我正在學(xué)習(xí)Swift:我應(yīng)該學(xué)習(xí)SwiftUI還是我也需要學(xué)習(xí)UIKit飒焦?”
人們似乎想聽(tīng)到的答案是“忘記舊的UIKit了,您應(yīng)該專(zhuān)注于SwiftUI!”然而牺荠,一個(gè)簡(jiǎn)單的事實(shí)是翁巍,絕大多數(shù)人都不會(huì)從該建議中獲得成功,這值得解釋為什么一點(diǎn)細(xì)節(jié)休雌。
在開(kāi)始詳細(xì)介紹之前灶壶,我想澄清一件事:SwiftUI是一個(gè)了不起的用戶界面框架,并且絕對(duì)會(huì)100%成為Apple平臺(tái)上應(yīng)用程序開(kāi)發(fā)的未來(lái)杈曲。但是驰凛,如果您想今天(或在未來(lái)一到兩年左右的任何時(shí)間)構(gòu)建出色的應(yīng)用程序,那么您也100%絕對(duì)需要UIKit的知識(shí)担扑,特別是如果您打算使應(yīng)用程序開(kāi)發(fā)成為您的職業(yè)恰响。
好的,順便說(shuō)一句涌献,在忽略UIKit的同時(shí)關(guān)注SwiftUI的問(wèn)題歸結(jié)為三點(diǎn):
API覆蓋范圍有限渔隶。
限制采用。
支持有限洁奈。
讓我們分解一下……
API覆蓋范圍有限
無(wú)論您是想在公司工作還是在業(yè)余時(shí)間開(kāi)發(fā)業(yè)余愛(ài)好應(yīng)用程序间唉,SwiftUI的一個(gè)缺點(diǎn)是它目前沒(méi)有與UIKit一樣廣泛的API覆蓋范圍。
例如利术,如果要在網(wǎng)格中顯示項(xiàng)目呈野,可以UICollectionView在UIKit中使用,但是SwiftUI沒(méi)有等效項(xiàng)印叁”幻埃或者,如果您想讓用戶輸入多行文本轮蜕,可以UITextView在UIKit中使用昨悼,但是SwiftUI也沒(méi)有等效項(xiàng)。
這并不是蘋(píng)果公司的懶惰跃洛,而是故意的:他們不是先發(fā)布所有API的包裝器率触,而是在以后進(jìn)行更改,而是采取更為謹(jǐn)慎的方法并逐步添加API汇竭。(我希望4谢取)這應(yīng)該減少我們將來(lái)看到的重大更改的數(shù)量,因?yàn)樗笰pple的工程師有更多的時(shí)間來(lái)細(xì)化他們打算交付的API子集细燎。
很多時(shí)候两曼,您會(huì)找到解決方法,但是老實(shí)說(shuō)玻驻,當(dāng)您知道某個(gè)特定的東西在UIKit中是微不足道的悼凑,但是在SwiftUI中不是不可能的時(shí)候,這很累。有時(shí)甚至很簡(jiǎn)單:如何更改表上的分隔符插入户辫?或如何將文本框添加到警報(bào)中益老?這些是UIKit中的單行代碼,但在SwiftUI中不可用寸莫。
隨著時(shí)間的流逝捺萌,我完全希望看到SwiftUI會(huì)增加更多功能,使其與UIKit達(dá)到同等水平膘茎,但是現(xiàn)在我們還有很長(zhǎng)的路要走桃纯。
限制采用
SwiftUI僅在WWDC2019上宣布,并且可在iOS 13設(shè)備或更高版本中使用披坏。這立即意味著:
迄今為止态坦,幾乎所有編寫(xiě)的應(yīng)用程序都使用UIKit。
任何需要支持iOS n-1或n-2的應(yīng)用程序(例如iOS 12和iOS 11)甚至都無(wú)法開(kāi)始使用SwiftUI一年或更長(zhǎng)時(shí)間棒拂。
這意味著伞梯,如果您打算在未來(lái)三年內(nèi)找到一份iOS開(kāi)發(fā)人員的工作,則UIKit經(jīng)驗(yàn)實(shí)際上是必不可少的帚屉,因?yàn)檫@是現(xiàn)有代碼庫(kù)所使用的谜诫。實(shí)際上,我完全希望UIKit在四年后仍將是主導(dǎo)的UI平臺(tái)攻旦。我想沒(méi)有人-甚至沒(méi)有蘋(píng)果喻旷!–希望iOS社區(qū)能夠以任何快速的步伐遷移到SwiftUI。在UIKit應(yīng)用程序中有大量的代碼牢屋,大量的時(shí)間和大量的資金且预,并且它擁有漫長(zhǎng)而幸福的生活。
有些人試圖在采用Swift和采用SwiftUI之間劃清界限烙无,這沒(méi)有幫助锋谐。采用Swift的速度很快,因?yàn)樗梢栽贏pple支持的每個(gè)框架(UIKit截酷,SpriteKit等)中工作涮拗,并且還已經(jīng)支持iOS n-1,因此許多公司可以立即切換到它合搅。
再一次多搀,我想重申歧蕉,SwiftUI絕對(duì)將成為Apple平臺(tái)開(kāi)發(fā)的未來(lái)灾部,但是要在UIKit級(jí)別獲得采用將需要很長(zhǎng)時(shí)間。
同時(shí)惯退,SwiftUI是個(gè)人應(yīng)用程序赌髓,愛(ài)好應(yīng)用程序,原型應(yīng)用程序或一般實(shí)驗(yàn)的理想選擇。如果您有幸加入專(zhuān)門(mén)使用SwiftUI的公司锁蠕,請(qǐng)盡情享受吧夷野!
有限的支持
UIKit已有十多年的歷史了,這意味著a)幾乎您可能遇到的每個(gè)問(wèn)題都已經(jīng)被他人解決荣倾,并且b)那里有許多提供擴(kuò)展和自定義功能的庫(kù)悯搔。
盡管有些學(xué)習(xí)者可能會(huì)想到高級(jí)開(kāi)發(fā)人員會(huì)掌握大量UIKit,但簡(jiǎn)單的事實(shí)是舌仍,我們所有人都使用Google妒貌,Stack Overflow,利用Swift進(jìn)行黑客入侵等工具來(lái)找到問(wèn)題的解決方案铸豁。當(dāng)您絕望時(shí)灌曙,這可能實(shí)際上是將錯(cuò)誤消息粘貼到網(wǎng)站中,但是無(wú)論您如何獲得答案节芥,它都可以節(jié)省大量在線查找錯(cuò)誤消息的時(shí)間在刺。
SwiftUI僅憑借顯著更新而已,可用的解決方案卻少得多头镊。實(shí)際上蚣驼,尋找從未有人嘗試過(guò)的東西很普遍–實(shí)際上,您是第一人相艇。這可能會(huì)很有趣隙姿,但是如果您有一個(gè)實(shí)際要交付的實(shí)際項(xiàng)目,那也可能會(huì)令人沮喪厂捞。
所以……您是說(shuō)我不應(yīng)該學(xué)習(xí)SwiftUI嗎输玷?
沒(méi)有!SwiftUI非常有趣靡馁,您可以用它來(lái)構(gòu)建奇妙的東西欲鹏。本書(shū)的其余全部?jī)?nèi)容旨在幫助您盡快高效地開(kāi)始使用SwiftUI –如果我不認(rèn)為SwiftUI很棒,我不會(huì)寫(xiě)它臭墨。
我要說(shuō)的是赔嚎,SwiftUI的存在并沒(méi)有以某種方式使UIKit過(guò)時(shí):如果您打算在未來(lái)三年內(nèi)獲得iOS開(kāi)發(fā)工作,那么知道如何使用UIKit將會(huì)是一項(xiàng)堅(jiān)定的要求或一個(gè)強(qiáng)大的要求胧弛。獎(jiǎng)金尤误。
因此,直接回答這個(gè)問(wèn)題:是的结缚,應(yīng)該忙于學(xué)習(xí)SwiftUI损晤,因?yàn)檫@是在蘋(píng)果平臺(tái)上進(jìn)行應(yīng)用程序開(kāi)發(fā)的未來(lái),但是您仍然需要學(xué)習(xí)UIKit红竭,因?yàn)檫@些技能在未來(lái)幾年中將非常有用尤勋。
隨著時(shí)間的流逝喘落,隨著SwiftUI的實(shí)力,采用和支持的增長(zhǎng)最冰,以及隨著SwiftUI的增長(zhǎng)瘦棋,UIKit將開(kāi)始縮小,上面列出的所有三個(gè)問(wèn)題都將得到減少暖哨。但是赌朋,至少目前至少確實(shí)需要兩者。
SwiftUI可以在哪里使用篇裁?
SwiftUI在iOS 13箕慧,macOS 10.15,tvOS 13和watchOS 6或這些平臺(tái)的任何更高版本上運(yùn)行茴恰。這意味著颠焦,如果您使用的應(yīng)用程序必須支持iOS N-1甚至N-2(即當(dāng)前版本和該版本之前的一兩個(gè)版本),那么您甚至需要一兩年的時(shí)間才能考慮遷移到SwiftUI 往枣。
但是伐庭,重要的是不要將SwiftUI視為類(lèi)似于Java的Swing或React Native的多平臺(tái)框架。官方說(shuō)法似乎是分冈,SwiftUI不是一個(gè)多平臺(tái)框架圾另,而是一個(gè)用于在多個(gè)平臺(tái)上創(chuàng)建應(yīng)用程序的框架。
聽(tīng)起來(lái)可能是一樣的雕沉,但是有一個(gè)重要的區(qū)別:Apple并不是說(shuō)您可以在每個(gè)平臺(tái)上使用相同的SwiftUI代碼集乔,因?yàn)橛行┦虑槭遣豢赡艿抹C無(wú)法在Mac上使用Apple Watch的數(shù)字王冠例如,并且類(lèi)似地在watchOS應(yīng)用上具有選項(xiàng)卡欄也將無(wú)法工作坡椒。
SwiftUI會(huì)取代UIKit嗎扰路?
不會(huì)。SwiftUI的許多部分都直接建立在現(xiàn)有UIKit組件之上倔叼,例如UITableView汗唱。當(dāng)然,許多其他部分則沒(méi)有丈攒,它們是SwiftUI而非UIKit呈現(xiàn)的新控件哩罪。
但是重點(diǎn)不是UIKit涉及的程度。相反巡验,關(guān)鍵是我們不在乎际插。SwiftUI或多或少完全掩蓋了UIKit的行為,因此显设,如果您為SwiftUI編寫(xiě)應(yīng)用程序框弛,并且Apple在兩年內(nèi)用唱的大象代替了UIKit,那么您不必在乎–只要Apple使大象具有相同的方法和屬性即可該UIKit暴露于SwiftUI敷硅,您的代碼不變功咒。
SwiftUI是否使用自動(dòng)布局愉阎?
盡管Auto Layout肯定會(huì)在幕后用于某些事情绞蹦,但作為SwiftUI設(shè)計(jì)師并沒(méi)有暴露給我們力奋。取而代之的是,它使用了靈活的盒式布局系統(tǒng)幽七,這對(duì)于來(lái)自Web的開(kāi)發(fā)人員來(lái)說(shuō)將是熟悉的景殷。
SwiftUI快嗎?
SwiftUI是令人訝異的快-在所有我的測(cè)試中澡屡,到目前為止猿挚,似乎超越的UIKit。與做到這一點(diǎn)的團(tuán)隊(duì)交談后驶鹉,我開(kāi)始明白為什么:首先绩蜻,他們積極地扁平化圖層層次結(jié)構(gòu),這樣系統(tǒng)就不必做更多的繪制了室埋,但是第二步办绝,很多操作完全繞過(guò)了Core Animation,直接去了Metal進(jìn)行了額外的處理姚淆。速度孕蝉。
所以,是的:SwiftUI的速度非畴绶辏快降淮,而且所有這些都無(wú)需我們做任何額外的工作。
為什么看不到我的代碼預(yù)覽搏讶?
使用SwiftUI時(shí)佳鳖,能夠同時(shí)查看視圖代碼和視圖預(yù)覽(外觀)非常有幫助。如果您可以看到代碼而不是預(yù)覽媒惕,則可能是您尚未升級(jí)到macOS 10.15腋颠;必須進(jìn)行預(yù)覽才能正常工作。
代碼與預(yù)覽的匹配程度如何吓笙?
對(duì)預(yù)覽進(jìn)行任何更改時(shí)淑玫,它也會(huì)更新生成的代碼。同樣面睛,如果更改代碼絮蒿,它也會(huì)更新用戶界面。因此叁鉴,代碼和預(yù)覽是相同的土涝,并且始終保持同步。
為什么我的顏色看起來(lái)有點(diǎn)偏幌墓?
SwiftUI為我們提供了標(biāo)準(zhǔn)的系統(tǒng)顏色但壮,例如紅色冀泻,藍(lán)色和綠色,但是這些并不是您習(xí)慣于使用的純紅色蜡饵,藍(lán)色和綠色UIColor弹渔。取而代之的是,這些是可以自動(dòng)適應(yīng)明暗模式的新樣式顏色溯祸,這意味著根據(jù)您的系統(tǒng)外觀肢专,它們看起來(lái)會(huì)更亮或更暗。
UIKit死了嗎焦辅?
沒(méi)有博杖!蘋(píng)果在本周的WWDC上播出了大量的新UIKit功能。如果Apple仍在WWDC上談?wù)揢IKit的新功能筷登,那您就很安全-沒(méi)有使他們驚訝地淘汰它的風(fēng)險(xiǎn)剃根。
您可以混合使用SwiftUI和UIKit的視圖嗎?
是!?您可以將一個(gè)嵌入另一個(gè)前方,效果很好狈醉。