曰本美女∴一区二区特级A级黄色大片, 国产亚洲精品美女久久久久久2025, 页岩实心砖-高密市宏伟建材有限公司, 午夜小视频在线观看欧美日韩手机在线,国产人妻奶水一区二区,国产玉足,妺妺窝人体色WWW网站孕妇,色综合天天综合网中文伊,成人在线麻豆网观看

您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費注冊]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>數(shù)值算法/人工智能>

如何使用協(xié)議的實現(xiàn) MVVM 架構(gòu)

大小:0.4 MB 人氣: 2017-10-11 需要積分:1

  在 Swift 中用值類型來替代引用類型,比以前在 Objective-C 中要容易許多,這可以讓您的代碼更簡潔,并且更不容易出錯。然而,當(dāng)需要在多個類型當(dāng)中共享代碼的時候,許多人往往會回避使用值類型,而轉(zhuǎn)為使用繼承來實現(xiàn)。

  通過 Natasha 在 do{iOS} 2015上對 MVVM 的介紹,您可以學(xué)習(xí)到如何使用協(xié)議來實現(xiàn)這個功能,而不再采用繼承的方式!Natasha The Robot 將會引導(dǎo)您跟隨她學(xué)習(xí)和使用面向協(xié)議編程的過程,使用 Swift 2.0 的特性來創(chuàng)建漂亮、穩(wěn)定的代碼。

  About the Speaker: Natasha Murashev

  Natasha 喜歡學(xué)習(xí) Swift 和 iOS 開發(fā),她暗喻自己是一名“機(jī)器人”。此前,她曾經(jīng)在位于舊金山 Capital One 公司工作,任職 iOS 資深工程師,但是如今她正四處旅行,撰寫她學(xué)習(xí)新技術(shù)的心得體會。在她空余的時候,她會將時間花在她的個人項目、在聚會沙龍和大會上進(jìn)行演講、向開源項目貢獻(xiàn)代碼,以及實現(xiàn)她愿望清單上列出的各項事宜。

  為什么要簡化 Swift 中的代碼呢? (0:00)

  嗨,我是 Natasha。就是 Twitter 上的 @NatashaTheRobot。關(guān)于我的個人介紹的話我還想多說一些:我有一個 每日 Swift 周報,還有一個寫了許多關(guān)于 Swift 文章的博客,自 Swift 第一天推出以來,我就已經(jīng)在大量地研究 Swift 了。

  作為一名 Objective-C 開發(fā)者,我基本上是在 Swift 剛剛推出的時候開始學(xué)習(xí) Objective-C 代碼的——這導(dǎo)致我使用了很多的引用類型。我習(xí)慣性將所有東西聲明為類,因為我已經(jīng)習(xí)慣了面向?qū)ο缶幊獭_@也正是 Objective-C 的思想。

  我覺得我自己的編程習(xí)慣還是很不錯的了,因為我有些時候還是會使用枚舉的。它們比普通的枚舉要復(fù)雜得多,這讓我覺得很不錯。然而,當(dāng)我開始參加各種活動然后聽取演講之后,尤其是 Andy Matuschak關(guān)于控制 Swift 代碼復(fù)雜度的演講之后,我就豁然開朗了。他提到要使用值類型。直到這個時候,我才知道 Swift 當(dāng)中有結(jié)構(gòu)體,但是作為一名從 Objective-C 轉(zhuǎn)向 Swift 的開發(fā)者,對我來說以類來起步是很自然的一件事情。

  這次演講給我留下了很深的印象,我覺得應(yīng)該要盡可能將所有東西都應(yīng)用上值類型。事實上,他發(fā)現(xiàn)絕大多數(shù) Swift 標(biāo)準(zhǔn)庫中的東西都是使用的值類型,并且語言的創(chuàng)造者本身也在使用值類型。我回到我的工作項目當(dāng)中,然后創(chuàng)建了一個新文件,準(zhǔn)備從此開始實驗值類型的強(qiáng)大之處。

  最初,我有這樣一個感覺:“我是一名 Swift 開發(fā)者了!我在使用結(jié)構(gòu)體了!”,但是后來有些需求不得不讓我轉(zhuǎn)而使用繼承,這感覺非常糟糕,但是我不知道該如何解決這個問題,直到……

  面向協(xié)議編程 (2:28)

  在今年的 WWDC 上,有一個難以置信的演講,講述了在 Swift 中進(jìn)行面向協(xié)議編程。在這里,他們解釋了如何用協(xié)議來替代繼承。如果您沒有看過這個演講并且打算轉(zhuǎn)向 Swift 進(jìn)行開發(fā)的話,那么我覺得這是自去年的 WWDC 以來,最為重要的一個演講了。

  在這個演講中, Apple Swift 標(biāo)準(zhǔn)庫的技術(shù)總監(jiān) Dave Abrahams提到了:

  “Swift 是一門面向協(xié)議的編程語言。”

  在視頻當(dāng)中,他演講的標(biāo)題是“醍醐灌頂?shù)闹v解 (Professor of Blowing Your Mind)”,他成功做到了這一點,我以及每一名觀眾都能感受到這一點。

  這對我們來說并不是一個全新的概念:我們已經(jīng)見識過 Apple 使用了大量的協(xié)議,比如說 TableView 當(dāng)中,我們都覺得這是一個很棒的設(shè)計模式,因為沒有人希望每時每刻都要繼承 UITableViewController。相反,您可以使用協(xié)議來告訴 Apple 您需要多少個表視圖單元格。我們已經(jīng)知曉了這種設(shè)計模式的魅力所在,而現(xiàn)在我們需要把它帶到一個全新的高度。

  對于我來說,我對此非常興奮。我已經(jīng)迫不及待回到電腦面前,更詳細(xì)地研究這個設(shè)計模式,成為一名“面向協(xié)議的程序員”。我隨后帶著興奮回去處理我的那些工作。在我的工作當(dāng)中,我已經(jīng)有了一個正在使用的代碼庫,它當(dāng)中帶有了已經(jīng)確定并建立的模式。這很難向其中加入新的東西,也很難理解應(yīng)該如何使用它。我想要使用面向協(xié)議編程,但是我覺得我已經(jīng)受限于我的既有項目了,我不知道該如何才能更進(jìn)一步。

  MVVM - 將事情留到第二天再考慮 (5:00)

  我的腦海里一直在思考著關(guān)于協(xié)議的相關(guān)內(nèi)容,我在想“我該怎么將協(xié)議整合到我的代碼當(dāng)中呢?”這件事情一直停留在我的腦海里,揮之不去,但是我不知道該如何做到這一點。然后,我就去睡了一覺。我非常強(qiáng)烈推崇這種做法,盡管對于程序員來說,他們的聲譽(yù)往往在于“不達(dá)目的不罷休”。對于我來說,睡一覺可以幫助我解決很多問題,很可能是因為我們的大腦在睡眠的時候可以更好地處理信息。

  睡了一覺之后,我醒來發(fā)現(xiàn)所有的東西都迎刃而解了。我想我至少能夠在我的工作代碼中應(yīng)用一個用例,這讓我十分興奮。這個用例就是使用 MVVM。

  對那些不熟悉 MVVM 的人來說,您可以去閱讀 Ash Furrow 的這篇博文:Swift 中的 MVVM。同樣在 objc.io上還有一篇叫做 “MVVM 介紹” 的文章。我會使用一個簡單的例子來介紹,所以希望大家能夠看到 MVVM 是如何工作的。

  我曾經(jīng)在一家銀行工作。比如說您有一個模型,里面包含了關(guān)于賬戶余額的一些原始數(shù)據(jù)。在模型層當(dāng)中,您想要保留這個值,作為原始的 NSDecimalNumber。

  letamount = 6729383.99

  當(dāng)您向用戶展示相同數(shù)字的時候,您可能想要轉(zhuǎn)換其顯示樣式,例如說:“您的賬戶余額為……”,然后在您的視圖當(dāng)中添加 “$” 標(biāo)識,并且進(jìn)行格式化:

  Your balance is $6,729,383.99

  許多人喜歡將這種代碼放到視圖控制器當(dāng)中。這往往會導(dǎo)致視圖控制器變得臃腫不堪,從而難以測試。此外,您還可能將這種代碼放到模型當(dāng)中,從而讓模型也變得非常難看,因為有許多進(jìn)行格式化的代碼擠在其中。

  相反,您可以讓模型變得清晰,然后僅僅只用于映射您的原始數(shù)據(jù)。這是您視圖模型的初始狀態(tài):

  structAccountViewModel { letdisplayBalance: String init(mode: BankAccount) { letformattedBalance = model.balance.currencyValue displayBalance = “Your balance is\(formattedBalance)” } }

  您的視圖模型實際上會讀取您的數(shù)據(jù)模型,然后將其中的信息進(jìn)行格式化,從而準(zhǔn)備展示到視圖當(dāng)中。這就是視圖模型的魅力所在。這很容易進(jìn)行測試。您可以將帶有賬戶信息的模型放進(jìn)去,然后測試顯示就可以了,而在此之前,如果您想要測試您的視圖控制器或者視圖,這是非常非常難的,因為輸出特別紛繁復(fù)雜。

  Zoetrope 模型 (8:29)

  注意到我的視圖模型是值類型的。那么這個在 Swift 中是如何起作用的呢?

  關(guān)鍵在于,您的視圖控制器需要維持視圖模型的最新版本。值類型是一種數(shù)據(jù)類型。它不應(yīng)該成為真實的數(shù)據(jù),它只是數(shù)據(jù)在某個時間點的一份拷貝而已。您的視圖控制器需要跟蹤這些信息,決定哪個拷貝數(shù)據(jù)應(yīng)該展示給用戶(也就是最新的拷貝)。

  順便想想,在 Andy Matuschak 的演講中,那個關(guān)于 zoetrope 的例子。(在日本的 Ghibli 博物館中有這樣一個很神奇的西洋鏡)。

  這里的關(guān)鍵在于,zoetrope 的每一個幀都是靜態(tài)值。您可以通過改變?nèi)宋锸植刻鸬木嚯x,或者人物頭部傾斜的角度,來對字符進(jìn)行編碼。每一幀都是靜態(tài)的,但是當(dāng)您把它們放到一起,然后一直看向一個中心的話,那么始終都會有新的數(shù)據(jù)出現(xiàn),這樣您就可以得到一個美麗、生動的動畫。

  您可以用相同的方式來實現(xiàn)值類型。您的視圖控制器將會跟蹤 zoetrope 的最后一個幀圖像——也就是最新的一塊活躍數(shù)據(jù),然后將其展示給用戶。只要您的模型發(fā)生了更新,也就是有了新的數(shù)據(jù),這樣您就可以通過計算得到一個新的視圖模型。現(xiàn)在,您的視圖就會根據(jù)最新的信息進(jìn)行更新了。

  var viewModel =ViewModel(model: Account)

  沒有協(xié)議之前的丑陋 (9:57)

  現(xiàn)在,我們已經(jīng)得到了令人興奮的部分了。我現(xiàn)在將會運行一個非常簡單的例子。在這個表視圖當(dāng)中,比如說絕大多數(shù)應(yīng)用都會有的設(shè)置屏幕,試想我只有一個設(shè)置:用一個滑塊 (slider) 來將整個應(yīng)用主色調(diào)變?yōu)辄S色。

  這個操作應(yīng)該是非常簡單的,但是它也會變得很復(fù)雜。這里有一個問題:在我們的表視圖單元格當(dāng)中,其中的每一個單獨組件都需要以某種方式來進(jìn)行格式化。如果其中有標(biāo)簽 (label) 的話,那么您必須要定義它的字體,字體顏色,字體大小,等等。如果是開關(guān) (switch) 的話,那么當(dāng)開關(guān)打開的時候會發(fā)生些什么?初始狀態(tài)是關(guān)閉還是打開?對于這種擁有這兩個元素的簡單的表視圖單元格來說,我已經(jīng)有 6 種不同的方式來對它進(jìn)行配置:

  classSwitchWithTextTableViewCell: UITableViewCell{ func configure( title: String, titleFont: UIFont, titleColor: UIColor, switchOn: Bool, switchColor: UIColor= .purpleColor(), onSwitchToggleHandler: onSwitchTogglerHandlerType? = nil) { // 在這里配置視圖 } }

  您可以想象得到,我們絕大多數(shù)人進(jìn)行配置的表視圖單元格比著遠(yuǎn)復(fù)雜得多。在我的代碼當(dāng)中,這種 configure 方法將非常非常累贅。添加一個副標(biāo)題將會導(dǎo)致多出額外的三個屬性需要設(shè)置。在 Swift 中您可以用默認(rèn)值來獲得一些輔助,但是使用這種臃腫的 configure 方法不是非常簡潔。

  在您實際上調(diào)用此方法的視圖控制器當(dāng)中,我們持有了所有存放在其中的信息棧。它看起來并不是很好看;這讓人感覺很不好,但是我一直沒想到有更好的辦法,直到協(xié)議的出現(xiàn)。

  視圖模型及協(xié)議 (12:05)

  對于單元格來說,我們不應(yīng)該使用這些臃腫的配置方法,而是應(yīng)該將每個部分單獨拿出來,然后將其放大一個 SwiftchWithTextCellProtocol 的協(xié)議當(dāng)中。這讓我感覺到非常開心。這樣子,我就可以讓我的視圖模型實現(xiàn)這個協(xié)議,然后在這里設(shè)置所有的屬性?,F(xiàn)在,我就不用再去使用臃腫的配置方法了,但是我仍然需要有一種方式來確保每個單獨的屬性實際上都被設(shè)置了。

  protocol SwitchWithTextCellProtocol { vartitle: String { get} vartitleFont: UIFont { get} vartitleColor: UIColor { get} varswitchOn: Bool { get} varswitchColor: UIColor { get} func onSwitchToggleOn(on: Bool) }

  通過 Swift 2.0 當(dāng)中的協(xié)議擴(kuò)展,我就可以通過默認(rèn)值做一些處理了。如果對于大多數(shù)單元格來說,可以確定某一種顏色的話,那么您就可以對其建立擴(kuò)展,然后設(shè)置該顏色即可。所有的實現(xiàn)此協(xié)議的視圖模型都沒必要再去設(shè)置這個顏色了。這個做法非常棒:

  extension SwitchWithTextCellProtocol { varswitchColor: UIColor { return.purpleColor() } }

  現(xiàn)在,我的 configure 方法只需要獲取某個實現(xiàn)此協(xié)議的值就可以了:

  classSwitchWithTextTableViewCell: UITableViewCell{func configure(withDelegate delegate:SwitchWithTextCellProtocol) { //在這里配置方法 } }

  這個方法只有一個參數(shù),這對之前的那個六個參數(shù)(甚至更多)的方法來說是一個重大的改進(jìn)。這是我現(xiàn)在的視圖模型的一個示例:

  structMinionModeViewModel: SwitchWithTextCellProtocol { vartitle = “Minion Mode?。?!”varswitchOn = truevarswitchColor: UIColor { return.yellowColor() } funconSwitchToggleOn(on: Bool) { ifon { print(“The Minions are here to stay!”) } else{ print(“The Minions went out to play!”) } } }

  它實現(xiàn)了這個協(xié)議,然后配置了所有相關(guān)的信息。正如您在前面的示例中看到的那樣,您可以用您的模型對象來初始化視圖模型了?,F(xiàn)在,如果您需要諸如外匯收益之類的信息的話,您實際上可以在您視圖模型的各個地方使用這個信息,以便能夠指明如何對其進(jìn)行配置,并將視圖展示出來。

  因此,這個操作將會非常簡單?,F(xiàn)在,我的 cellForRowAtIndexPath() 也變得非常的簡明了:

  // YourViewController.swiftletcell = tableView.dequeueReusableCellWithIdentifier(“SwitchWithTextTableViewCell”, forIndexPath: indexPath) as! SwitchWithTextTableViewCell // This is where the magic happens!cell.configure(withDelegate: MinionModeViewModel()) returncell

  我將單元格 dequeue 出來,然后調(diào)用了我視圖模型的 configure 方法。在這個例子當(dāng)中,我沒有對它的 frame 進(jìn)行任何的配置,它同樣也沒有包含模型層,但是您同樣可以將這個模型放到視圖控制器層級,以便對其進(jìn)行跟蹤。您同樣可以在視圖模型當(dāng)中傳遞這些信息,這樣您的單元格就可以生成了。當(dāng)我們重構(gòu)之后,我們只需要三行代碼就可以完成配置了。

  進(jìn)一步的抽象 (14:10)

  這個時候,我為自己的做法感到非常開心。因為我把這個臃腫的帶有六個參數(shù)的 configure 方法,用協(xié)議的方式將其進(jìn)行了重構(gòu)。我發(fā)現(xiàn)使用協(xié)議能夠讓我的代碼更優(yōu)美、更簡潔,邏輯更清晰。

  通常情況下,我的下一步動作就是通過博客把它發(fā)表出來。我喜歡為了總結(jié)學(xué)習(xí)經(jīng)驗而寫博客,因此無論我是學(xué)到了什么還是發(fā)現(xiàn)了什么,我都會在博客中把它寫出來。我的博客上已經(jīng)講述了這一點,有人發(fā)帖評論說:“有沒有考慮創(chuàng)建兩個協(xié)議呢?一個作為實際編碼信息的數(shù)據(jù)源,就比如說單元格的標(biāo)題之類的東西,也就是實際的數(shù)據(jù)?!焙皖伾?、字體之類的信息不同,它們應(yīng)該是相互獨立的,因為字體之類的信息更多是關(guān)于格式化方面的,而其中并沒有包含實際的數(shù)據(jù),并且這種模式我們已經(jīng)可以看到 Apple 用過了,比如說在 UITableViewCells 或者集合視圖之類的地方。

  我認(rèn)為這是一個非常絕妙的想法。我將我的邏輯進(jìn)行了分離,然后再創(chuàng)建了單元格數(shù)據(jù)存儲和單元格委托:

  protocol SwitchWithTextCellDataSource { vartitle: String { get} varswitchOn: Bool { get} } protocol SwitchWithTextCellDelegate { func onSwitchToggleOn(on: Bool) varswitchColor: UIColor { get} vartextColor: UIColor { get} varfont: UIFont { get} }

  接下來,我讓我的 configure 方法同時接收這兩個協(xié)議。因為委托可以全部在協(xié)議擴(kuò)展中使用默認(rèn)值進(jìn)行配置,比如說字體、顏色之類的信息,這樣在理論上我可以不用向里面?zhèn)鬟f任何東西進(jìn)去;我可以只用創(chuàng)建一個模型就可以了:

  // SwitchWithTextTableViewCellfunc configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) { // 在這里配置視圖}

  現(xiàn)在我可以使用擴(kuò)展來改進(jìn)我的視圖模型了。我會使用一個實現(xiàn)數(shù)據(jù)源的代碼塊,然后給定要傳遞給視圖當(dāng)中的原始信息:

  structMinionModeViewModel: SwitchWithTextCellDataSource { vartitle = “Minion Mode?。?!”varswitchOn = true}

  接下來,我會在一個單獨的視圖模型的部分當(dāng)中使用處理字體、顏色之類的委托,然后在其中進(jìn)行相關(guān)的配置。

  extension MinionModeViewModel: SwitchWithTextCellDelegate { var switchColor: UIColor { return.yellowColor() } func onSwitchToggleOn(on: Bool) {ifon{print(“The Minions are here to stay!”) } else{ print(“The Minions went out to play!”) } } }

  最終,我的表視圖單元格變得非常簡單:

  // SettingsViewControllerletviewModel = MinionModeViewModel() cell.configure(withDataSource: viewModel, delegate: viewModel) returncell

  我僅僅只用創(chuàng)建了我的視圖模型,然后將其傳遞到配置方法當(dāng)中,然后返回單元格,就完畢了。

  Swift 2.0 中的 Mixin 和 Trait (16:32)

  我對這一點還是比較滿意的。我創(chuàng)建了協(xié)議,簡化了我的代碼,然后發(fā)表了相關(guān)的博客,學(xué)習(xí)到了相關(guān)的知識。接著,我又讀到了一個非常贊的文章,我覺得大家都應(yīng)該去讀一讀:@mhollemans 寫的 Swift 2.0 中的 Mixin 和 Trait。Matthijs 講述的是游戲開發(fā),雖然我對此并不是很熟悉,但是我們?nèi)匀豢梢匀ダ斫馑岬降幕靖拍睢?/p>

  在游戲開發(fā)當(dāng)中,通常會有著一個很龐大的層級關(guān)系,以及一系列的繼承。比如說“怪物”類型當(dāng)中,可能會有各種各樣的“怪物”。繼承在這里變得十分有意義。但是,隨著層級的擴(kuò)展,事情變得開始凌亂起來。

  如何使用協(xié)議的實現(xiàn) MVVM 架構(gòu)

  對于這種類型的層次結(jié)構(gòu)來說,剛開始的時候還好。不過隨著后面的發(fā)展,當(dāng)您遇到要設(shè)計一個也能夠射擊的怪物的時候,事情就變得麻煩起來了,因為城堡同樣也可以射擊,因為在城堡的頂端擁有大炮,因此您現(xiàn)在就必須要將這個“射擊輔助類”提取出來。當(dāng)您正在創(chuàng)建這些子類的時候,您會覺得這種做法是非常非常奇異的,但是這很快會變得越來越混亂,最終您將會寫出一團(tuán)亂麻般的代碼。

  Matthijs 重構(gòu)了這個代碼,這樣我們不再使用這些繼承對象的邏輯,比如說控制能夠射擊或者控制能夠治療的子類,而是將其提取成為協(xié)議,通過協(xié)議擴(kuò)展來實現(xiàn)這個功能。

  這使得代碼看起來更加簡潔,更容易理解。例如:

  class ZapMonster: GameObject, GunTrait, RenderTrait, HealthTrait, MovementTrait { 。。.}

  只需要看一看這個對象的類型,我就可以立刻理解這個對象擁有哪些功能,而不是去一個一個查看它的實現(xiàn)。我個人更加喜歡這樣的設(shè)計模式。

  在我們的應(yīng)用中應(yīng)用 Mixin (19:47)

  雖然剛剛的例子是關(guān)于游戲開發(fā)的,但是我希望我也能夠在我自己的代碼中對表視圖單元格應(yīng)用上這個功能。這樣就不用讓我實際的單元格實現(xiàn)這個協(xié)議了,我只需要將其與更寬泛的 TextPresentable 聯(lián)系在一起就可以了。這樣,任何擁有標(biāo)簽的視圖,而不僅僅只是單元格,都可以實現(xiàn)這個協(xié)議來完成相關(guān)的功能。這樣我就可以說這個標(biāo)簽當(dāng)中有什么樣的文本,什么樣的顏色,以及什么樣的字體:

  protocol TextPresentable { vartext: String { get} vartextColor: UIColor { get} varfont: UIFont { get} } protocol SwitchPresentable { varswitchOn: Bool { get} varswitchColor: UIColor { get} func onSwitchToggleOn(on: Bool) }

  Switch 擁有自己獨有的協(xié)議,這樣就可以知道它應(yīng)該如何配置了。您可以想象這個從游戲開發(fā)示例當(dāng)中得來的靈感:現(xiàn)在您需要一個圖像了,你只需要實現(xiàn) ImagePresentable 協(xié)議就可以了;現(xiàn)在您需要一個文本框了,只需要實現(xiàn) TextFieldPresentable 協(xié)議就可以了:

  protocol ImagePresentable { varimageName: String { get} } protocol TextFieldPresentable { varplaceholder: String { get} vartext: String { get} func onTextFieldDidEndEditing(textField: UITextField) }

  通過協(xié)議擴(kuò)展,您可以配置所有的字體和顏色,因此每一個單獨實現(xiàn)這個 TextPresentable 協(xié)議的視圖都會擁有這個標(biāo)簽的默認(rèn)配置,因為通常情況下,您應(yīng)用中的標(biāo)簽基本上都是非常相似的:

  extension TextPresentable { vartextColor: UIColor { return.blackColor() } varfont: UIFont { return.systemFontOfSize(17) } }

  您甚至可以更進(jìn)一步,創(chuàng)建不同類型的標(biāo)簽,比如說標(biāo)題標(biāo)簽。或許它擁有確定的字體或者顏色,這就意味著您可以一遍又一遍地在您的應(yīng)用程序中重用這個標(biāo)簽。這樣當(dāng)您的設(shè)計師要求將所有的標(biāo)題顏色變成藍(lán)色的時候,這種做法將會非??焖?。您可以前往協(xié)議擴(kuò)展當(dāng)中,將其改變?yōu)樗{(lán)色,然后通過這一行代碼的變化,每一個擁有這個 HeaderTextPresentable 協(xié)議的視圖中的標(biāo)簽都會立刻改變。

  我十分喜歡這個設(shè)計模式。這是我現(xiàn)在單元格的模樣:

  class SwitchWithTextTableViewCell《T whereT: TextPresentable, T: SwitchPresentable》: UITableViewCell { privatevardelegate: T? func configure(withDelegate delegate: T) { // 在這里配置視圖} }

  在這種情況下,它沒有實現(xiàn)這些協(xié)議,但是它會期待某種實現(xiàn)這些協(xié)議的東西傳遞進(jìn)去,因此我們使用了泛型。這個單元格期待一個實現(xiàn)了 TextPresentableProtocol 以及 SwitchPresentableProtocol 的委托。這個配置方法并不關(guān)心傳遞進(jìn)去的對象。就我們而言,傳遞進(jìn)去的將是一個視圖模型,但是它所想要的只要是實現(xiàn)了這些協(xié)議的東西就可以了,現(xiàn)在,您就可以基于這些信息在單元格當(dāng)中配置所有東西了。

  extension MinionModeViewModel: TextPresentable { vartext: String{ return“Minion Mode”} vartextColor: UIColor { return.blackColor() } varfont: UIFont { return.systemFontOfSize(17.0) } }

  我們的視圖模型將擁有一個 TextPresentable 代碼塊,在其中您可以配置文本、顏色、字體,并且由于所有這些在協(xié)議擴(kuò)展當(dāng)中都已經(jīng)有默認(rèn)值了,您甚至都不用讓視圖模型去實現(xiàn)這些具體的內(nèi)容。

  對于 SwitchPresentable 也是一樣的。這個開關(guān)應(yīng)該開啟還是關(guān)閉?當(dāng)開關(guān)開啟的時候應(yīng)該發(fā)生些什么?這里,您可以看到這個視圖的一小部分:

  extension MinionModeViewModel: SwitchPresentable { varswitchOn: Bool { returnfalse} varswitchColor: UIColor { return.yellowColor() } func onSwitchToggleOn(on: Bool) { ifon { print(“The Minions are here to stay!”) } else{ print(“The Minions went out to play!”) } } }

  最后,視圖控制器當(dāng)中的代碼就變得十分簡單:您只需要 dequeue 相應(yīng)的單元格。然后通過視圖模型對其進(jìn)行配置,然后返回單元格即可。其中一個關(guān)鍵的地方是,因為我們使用的是泛型,因此我們必須要指明 T 是什么東西,在我們的例子當(dāng)中,T 是視圖模型。

  Swift: 一個正在發(fā)展的語言 (24:02)

  在這一點上我是非常興奮的。我已經(jīng)經(jīng)歷了三種不同的迭代版本了。然而,Swift 仍然是一門新語言,它只出現(xiàn)了不到兩年的時間。在這個過程中它變化了很多,我們作為一個社區(qū)必須要決定 Swift 的最佳用例是什么。

  我一直在想一件事情,當(dāng)我在我的代碼中發(fā)現(xiàn)或者是提出某個新的設(shè)計模式的時候,該如何才能夠輕松地進(jìn)行遷移。這使得我切實相信:

  世上唯一不變的事就是變化本身。

  這句話特別適用于編程界。我通常會花費一個季度的時間來重寫我的每個應(yīng)用,因為最終您可能會需要改變很多東西;您需要添加單元測試,或者需要為了 iOS 7 重新設(shè)計。Apple 有時候會推出新的東西,因此您可能需要刪除或者添加新的功能;任何東西都在不斷的變化。

  因此,我總是在認(rèn)定我的代碼即將被改變的這種假設(shè)下進(jìn)行工作的。對于長期的產(chǎn)品開發(fā)來說,我必須要考慮到我正在用的這個設(shè)計模式是否允許我簡單地進(jìn)行修改,而不是對一個類進(jìn)行一個細(xì)小的變化就得祈禱這個操作不會發(fā)生崩潰。對于我來說,這個設(shè)計模式是非常贊的,因為它允許快速地進(jìn)行修改。

  假如說我的產(chǎn)品經(jīng)理過來跟我說:“哎,對于這個單元格,我希望讓它能夠添加一個圖像”。剛開始的時候,我們只有標(biāo)簽和開關(guān),而現(xiàn)在只是多了一個圖像而已。因此,我會讓這個單元格期待一個還實現(xiàn)了 ImagePresentableProtocol 的東西傳遞進(jìn)去,這就是我在單元格層面所做的全部操作。

  我同樣也必須要更新我的配置方法,以便能夠讓其能夠真正使用上這個圖像,但是這只需要使用兩行代碼就可以了。最后,我只是對我的視圖模型進(jìn)行擴(kuò)展就可以了。

  extension MinionModeViewModel: ImagePresentable { varimageName: String{ return“minionParty.png”} }

  開心的 Natasha the Robot:總結(jié) (26:26)

  這個時候我是非常開心的。這些就是我所要討論的所有東西了,在 MVVM 架構(gòu)中使用協(xié)議。

  使用協(xié)議來配置您的視圖使用協(xié)議擴(kuò)展來實現(xiàn)默認(rèn)值——這就是您設(shè)置用在您應(yīng)用當(dāng)中的所有字體、顏色以及配置的地方。這里最大的障礙就是處理子類了;這就是人們?yōu)槭裁纯偸鞘褂美^承——因為需要在多個類當(dāng)中使用相同的功能。使用視圖模型來為協(xié)議提供數(shù)據(jù)。您使用視圖模型的目的在于它們易于測試,并且變化帶來的耦合度很小。您的視圖控制器可以決定在最新版本的代碼當(dāng)中使用哪個版本的視圖模型。

  重點是我希望在明年的 WWDC 中,他們能夠提出一個適用于 Swift 的全新架構(gòu),或者有人能夠在這個演講之后在 Tweet 上給我一個更好的主意。對于那些使用 Swift 開發(fā)的人來說,我建議大家保持一個開放的心態(tài)。想想您該如何讓代碼變得更好。

  聽從您的同事、社區(qū)的建議??傆锌梢愿纳拼a的方式的,并且我確信我可以借此來進(jìn)行代碼的改善。在這一點上,我是非常高興的,不過我下周可能會讀到某些文章,這可能會導(dǎo)致我改變主意,或者學(xué)到一些新的東西。

  關(guān)于 Swift 的一個很酷的事情是,我們都有不同的編程經(jīng)驗。您的同事可能是函數(shù)式編程語言出身,也有可能是 Ruby 或者 .NET 出身——他們可能有與你不同的想法。由于 Swift 是一個不斷發(fā)展的語言,因此您需要虛心向別人學(xué)習(xí)。這能夠改善您的設(shè)計模式,并且能夠幫助您找到最好的設(shè)計模式。我認(rèn)為您總是可以對其進(jìn)行優(yōu)化和改進(jìn),分享您的發(fā)現(xiàn),然后周而復(fù)始。

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

如何使用協(xié)議的實現(xiàn) MVVM 架構(gòu)下載

相關(guān)電子資料下載

      發(fā)表評論

      用戶評論
      評價:好評中評差評

      發(fā)表評論,獲取積分! 請遵守相關(guān)規(guī)定!

      ?