色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

您好,歡迎來電子發燒友網! ,新用戶?[免費注冊]

您的位置:電子發燒友網>源碼下載>數值算法/人工智能>

如何使用協議的實現 MVVM 架構

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

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

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

  About the Speaker: Natasha Murashev

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

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

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

  作為一名 Objective-C 開發者,我基本上是在 Swift 剛剛推出的時候開始學習 Objective-C 代碼的——這導致我使用了很多的引用類型。我習慣性將所有東西聲明為類,因為我已經習慣了面向對象編程。這也正是 Objective-C 的思想。

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

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

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

  面向協議編程 (2:28)

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

  在這個演講中, Apple Swift 標準庫的技術總監 Dave Abrahams提到了:

  “Swift 是一門面向協議的編程語言?!?/p>

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

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

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

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

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

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

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

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

  letamount = 6729383.99

  當您向用戶展示相同數字的時候,您可能想要轉換其顯示樣式,例如說:“您的賬戶余額為……”,然后在您的視圖當中添加 “$” 標識,并且進行格式化:

  Your balance is $6,729,383.99

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

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

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

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

  Zoetrope 模型 (8:29)

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

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

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

  這里的關鍵在于,zoetrope 的每一個幀都是靜態值。您可以通過改變人物手部抬起的距離,或者人物頭部傾斜的角度,來對字符進行編碼。每一幀都是靜態的,但是當您把它們放到一起,然后一直看向一個中心的話,那么始終都會有新的數據出現,這樣您就可以得到一個美麗、生動的動畫。

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

  var viewModel =ViewModel(model: Account)

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

  現在,我們已經得到了令人興奮的部分了。我現在將會運行一個非常簡單的例子。在這個表視圖當中,比如說絕大多數應用都會有的設置屏幕,試想我只有一個設置:用一個滑塊 (slider) 來將整個應用主色調變為黃色。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  進一步的抽象 (14:10)

  這個時候,我為自己的做法感到非常開心。因為我把這個臃腫的帶有六個參數的 configure 方法,用協議的方式將其進行了重構。我發現使用協議能夠讓我的代碼更優美、更簡潔,邏輯更清晰。

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

  我認為這是一個非常絕妙的想法。我將我的邏輯進行了分離,然后再創建了單元格數據存儲和單元格委托:

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

  接下來,我讓我的 configure 方法同時接收這兩個協議。因為委托可以全部在協議擴展中使用默認值進行配置,比如說字體、顏色之類的信息,這樣在理論上我可以不用向里面傳遞任何東西進去;我可以只用創建一個模型就可以了:

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

  現在我可以使用擴展來改進我的視圖模型了。我會使用一個實現數據源的代碼塊,然后給定要傳遞給視圖當中的原始信息:

  structMinionModeViewModel: SwitchWithTextCellDataSource { vartitle = “Minion Mode?。。 眝arswitchOn = true}

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

  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

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

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

  我對這一點還是比較滿意的。我創建了協議,簡化了我的代碼,然后發表了相關的博客,學習到了相關的知識。接著,我又讀到了一個非常贊的文章,我覺得大家都應該去讀一讀:@mhollemans 寫的 Swift 2.0 中的 Mixin 和 Trait。Matthijs 講述的是游戲開發,雖然我對此并不是很熟悉,但是我們仍然可以去理解他提到的基本概念。

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

  如何使用協議的實現 MVVM 架構

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

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

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

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

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

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

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

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

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

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

  通過協議擴展,您可以配置所有的字體和顏色,因此每一個單獨實現這個 TextPresentable 協議的視圖都會擁有這個標簽的默認配置,因為通常情況下,您應用中的標簽基本上都是非常相似的:

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

  您甚至可以更進一步,創建不同類型的標簽,比如說標題標簽。或許它擁有確定的字體或者顏色,這就意味著您可以一遍又一遍地在您的應用程序中重用這個標簽。這樣當您的設計師要求將所有的標題顏色變成藍色的時候,這種做法將會非常快速。您可以前往協議擴展當中,將其改變為藍色,然后通過這一行代碼的變化,每一個擁有這個 HeaderTextPresentable 協議的視圖中的標簽都會立刻改變。

  我十分喜歡這個設計模式。這是我現在單元格的模樣:

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

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

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

  我們的視圖模型將擁有一個 TextPresentable 代碼塊,在其中您可以配置文本、顏色、字體,并且由于所有這些在協議擴展當中都已經有默認值了,您甚至都不用讓視圖模型去實現這些具體的內容。

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

  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!”) } } }

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

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

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

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

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

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

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

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

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

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

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

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

  使用協議來配置您的視圖使用協議擴展來實現默認值——這就是您設置用在您應用當中的所有字體、顏色以及配置的地方。這里最大的障礙就是處理子類了;這就是人們為什么總是使用繼承——因為需要在多個類當中使用相同的功能。使用視圖模型來為協議提供數據。您使用視圖模型的目的在于它們易于測試,并且變化帶來的耦合度很小。您的視圖控制器可以決定在最新版本的代碼當中使用哪個版本的視圖模型。

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

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

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

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

如何使用協議的實現 MVVM 架構下載

相關電子資料下載

      發表評論

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

      發表評論,獲取積分! 請遵守相關規定!

      ?
      主站蜘蛛池模板: 久久夜色噜噜噜亚洲AV0000 | 伊人久综合 | 高挑人妻无奈张开腿 | s8sp视频高清在线播放 | 国内免费视频成人精品 | 麻豆精品一卡2卡三卡4卡免费观看 | 亚洲一区精品在线 | 777精品久无码人妻蜜桃 | 一本之道高清在线观看免费 | 久久久久久久久久久福利观看 | 久久99热成人精品国产 | 97在线免费观看视频 | 亚洲黄色高清视频 | 最好看中文字幕国语 | 学生妹被爆插到高潮无遮挡 | 97超视频在线观看 | 双性人皇上被c到哭 | 中文字幕在线观看亚洲 | 国产午夜一级鲁丝片 | 国产精片久久久久久婷婷 | 69xx欧美 | 亚洲最大在线视频 | 摥管专用动态图399期 | 晓雪老师我要进你里面好爽 | 国产成人精品免费视频软件 | 日产国产欧美韩国在线 | 精品国产影院 | 碰超成人在线公开免费视频 | 蜜柚视频网在线观看免费 | www黄色com| a级毛片黄免费a级毛片 | 国偷自产视频一区二区久 | 熟女人妻久久精品AV天堂 | 在线观看永久免费网站 | a级成人免费毛片完整版 | 久久久久久久久免费视频 | 美丽的姑娘BD在线观看 | 免费乱理伦片在线观看八戒 | 色欲狠狠躁天天躁无码中文字幕 | 免费看毛片网 | 黄页免费观看 |