自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Swift 2.0 下面向協(xié)議的MVVM架構(gòu)實(shí)踐

移動(dòng)開發(fā) iOS
自從令人興奮的[《面向協(xié)議的編程方法》]在Swift的WWDC大會上發(fā)布以來。我對協(xié)議的使用考慮了很多。但是在現(xiàn)實(shí)中,我并沒有太多的顧及和使用這些功能。我還仍舊在消化到底面向協(xié)議的編程方法是什么,在代碼的哪些地方應(yīng)該使用,而不是使用我目前使用的`go-to`編程方法。

自從令人興奮的[《面向協(xié)議的編程方法》]在Swift的WWDC大會上發(fā)布以來。我對協(xié)議的使用考慮了很多。但是在現(xiàn)實(shí)中,我并沒有太多的顧及和使用這些功能。我還仍舊在消化到底面向協(xié)議的編程方法是什么,在代碼的哪些地方應(yīng)該使用,而不是使用我目前使用的`go-to`編程方法。

 

...所以,當(dāng)我想起來要在哪里應(yīng)用這些概念性的東西時(shí),我非常激動(dòng),那就是MVVM !我已經(jīng)在之前的博客中使用過MVVM架構(gòu),如果你想了解更多MVVM相關(guān)知識請參考[這里]。接下來我將講解,如何添加面向協(xié)議。

 

我將會使用一個(gè)簡單的例子。一個(gè)只有一個(gè)設(shè)置選項(xiàng)的設(shè)置頁面,把應(yīng)用設(shè)置為Minion模式,當(dāng)然你也可以擴(kuò)展為多個(gè)設(shè)置選項(xiàng)。

[[149011]]

View Cell

一個(gè)極其普通的Cell,它包含一個(gè)Label和一個(gè)開關(guān)控件。你也可以在其他地方使用這個(gè)Cell,例如注冊頁面添加一個(gè)“記住我”的開關(guān)選項(xiàng)。所以,你應(yīng)該保持這個(gè)頁面通用性。

一個(gè)復(fù)雜的配置

通常,我在cell中使用一個(gè)設(shè)置方法,來監(jiān)聽所有對應(yīng)用設(shè)置可能的變更,這看起來是這樣的:

  1. class SwitchWithTextTableViewCell: UITableViewCell { 
  2.  
  3. @IBOutlet private weak var label: UILabel! 
  4. @IBOutlet private weak var switchToggle: UISwitch! 
  5.  
  6. typealias onSwitchToggleHandlerType = (switchOn: Bool) -> Void 
  7. private var onSwitchToggleHandler: onSwitchToggleHandlerType? 
  8.  
  9. override func awakeFromNib() { 
  10. super.awakeFromNib() 
  11.  
  12. func configure(withTitle title: String, 
  13. switchOn: Bool, 
  14. onSwitchToggleHandler: onSwitchToggleHandlerType? = nil) 
  15. label.text = title 
  16. switchToggle.on = switchOn 
  17.  
  18. self.onSwitchToggleHandler = onSwitchToggleHandler 
  19.  
  20. @IBAction func onSwitchToggle(sender: UISwitch) { 
  21. onSwitchToggleHandler?(switchOn: sender.on) 

通過 Swift 的默認(rèn)參數(shù),可以添加其他的設(shè)置選項(xiàng)到這個(gè)設(shè)置方法,而不必改變代碼中的其他地方,使用起來非常方便。例如,當(dāng)設(shè)計(jì)師說開關(guān)按鈕的顏色需應(yīng)該各不相同,這時(shí)候我就可以添加一個(gè)默認(rèn)參數(shù)。

  1. func configure(withTitle title: String, 
  2. switchOn: Bool, 
  3. switchColor: UIColor = .purpleColor(), 
  4. onSwitchToggleHandler: onSwitchToggleHandlerType? = nil) 
  5. label.text = title 
  6. switchToggle.on = switchOn 
  7. // color option added! 
  8. switchToggle.onTintColor = switchColor 
  9.  
  10. self.onSwitchToggleHandler = onSwitchToggleHandler 

雖然在這種情況下看起來并不是什么大問題,但是隨著時(shí)間的增加,事實(shí)上這個(gè)方法將會變得非常冗長、復(fù)雜!是時(shí)候由面向協(xié)議的編程方法登場了。

面向協(xié)議的編程方法

  1. protocol SwitchWithTextCellProtocol { 
  2. var title: String { get } 
  3. var switchOn: Bool { get } 
  4.  
  5. func onSwitchTogleOn(on: Bool) 
  6.  
  7. class SwitchWithTextTableViewCell: UITableViewCell { 
  8.  
  9. @IBOutlet private weak var label: UILabel! 
  10. @IBOutlet private weak var switchToggle: UISwitch! 
  11.  
  12. private var delegate: SwitchWithTextCellProtocol? 
  13.  
  14. override func awakeFromNib() { 
  15. super.awakeFromNib() 
  16.  
  17. func configure(withDelegate delegate: SwitchWithTextCellProtocol) { 
  18. self.delegate = delegate 
  19.  
  20. label.text = delegate.title 
  21. switchToggle.on = delegate.switchOn 
  22.  
  23. @IBAction func onSwitchToggle(sender: UISwitch) { 
  24. delegate?.onSwitchTogleOn(sender.on) 

當(dāng)設(shè)計(jì)師說需要改變開關(guān)控件顏色的時(shí)候會發(fā)生什么?以下代碼可以展現(xiàn)協(xié)議擴(kuò)展的奇妙之處。

 

 

  1. extension SwitchWithTextCellProtocol { 
  2.  
  3. // set the default color here! 
  4. func switchColor() -> UIColor { 
  5. return .purpleColor() 
  6.  
  7. class SwitchWithTextTableViewCell: UITableViewCell { 
  8.  
  9. // truncated, see above 
  10.  
  11. func configure(withDelegate delegate: SwitchWithTextCellProtocol) { 
  12. self.delegate = delegate 
  13.  
  14. label.text = delegate.title 
  15. switchToggle.on = delegate.switchOn 
  16. // color option added! 
  17. switchToggle.onTintColor = delegate.switchColor() 

在以上代碼中協(xié)議的擴(kuò)展實(shí)現(xiàn)了默認(rèn)的switchColor選項(xiàng),所以,任何已經(jīng)實(shí)現(xiàn)了這個(gè)協(xié)議或者并不關(guān)心設(shè)置開關(guān)顏色的人,不用關(guān)注這個(gè)擴(kuò)展。只有一個(gè)具有不同顏色的新的開關(guān)控件可以實(shí)現(xiàn)。

ViewModel

所以現(xiàn)在剩下的事情將會非常簡單。我將會為MinionMode的設(shè)置cell寫一個(gè)ViewModel。

  1. import UIKit 
  2.  
  3. struct MinionModeViewModel: SwitchWithTextCellProtocol { 
  4. var title = "Minion Mode!!!" 
  5. var switchOn = true 
  6.  
  7. func onSwitchTogleOn(on: Bool) { 
  8. if on { 
  9. print("The Minions are here to stay!"
  10. else { 
  11. print("The Minions went out to play!"
  12.  
  13. func switchColor() -> UIColor { 
  14. return .yellowColor() 
  15.  
  16. ViewController 

 

***一步就是在ViewController中設(shè)置cell的時(shí)候?qū)iewModel傳給cell。

  1. import UIKit 
  2.  
  3. class SettingsViewController: UITableViewController { 
  4.  
  5. enum Setting: Int { 
  6. case MinionMode 
  7. // other settings here 
  8.  
  9. override func viewDidLoad() { 
  10. super.viewDidLoad() 
  11.  
  12. // MARK: - Table view data source 
  13.  
  14. override func tableView(tableView: UITableView, 
  15. numberOfRowsInSection section: Int) -> Int 
  16. return 1 
  17.  
  18. override func tableView(tableView: UITableView, 
  19. cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
  20. if let setting = Setting(rawValue: indexPath.row) { 
  21. switch setting { 
  22. case .MinionMode: 
  23. let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell 
  24.  
  25. // this is where the magic happens! 
  26. cell.configure(withDelegate: MinionModeViewModel()) 
  27. return cell 
  28.  
  29. return tableView.dequeueReusableCellWithIdentifier("defaultCell", forIndexPath: indexPath) 
  30.  

通過使用協(xié)議的擴(kuò)展,是面向協(xié)議的編程方法有了很大的意義,并且我在尋找更多的使用場景。以上代碼的全部內(nèi)容放在[github]上。

更新:將數(shù)據(jù)源和代理分開

在評論中,Marc Baldwin 建議分開cell的數(shù)據(jù)源和代理方法到兩個(gè)協(xié)議中,就像UITableView中的那樣。我很贊成這個(gè)意見,以下是我修改后的代碼。

View Cell

Cell將擁有兩個(gè)協(xié)議,并且任何一個(gè)協(xié)議都可以設(shè)置這個(gè)cell。

  1. import UIKit 
  2.  
  3. protocol SwitchWithTextCellDataSource { 
  4. var title: String { get } 
  5. var switchOn: Bool { get } 
  6.  
  7. protocol SwitchWithTextCellDelegate { 
  8. func onSwitchTogleOn(on: Bool) 
  9.  
  10. var switchColor: UIColor { get } 
  11. var textColor: UIColor { get } 
  12. var font: UIFont { get } 
  13.  
  14. extension SwitchWithTextCellDelegate { 
  15.  
  16. var switchColor: UIColor { 
  17. return .purpleColor() 
  18.  
  19. var textColor: UIColor { 
  20. return .blackColor() 
  21.  
  22. var font: UIFont { 
  23. return .systemFontOfSize(17
  24.  
  25. class SwitchWithTextTableViewCell: UITableViewCell { 
  26.  
  27. @IBOutlet private weak var label: UILabel! 
  28. @IBOutlet private weak var switchToggle: UISwitch! 
  29.  
  30. private var dataSource: SwitchWithTextCellDataSource? 
  31. private var delegate: SwitchWithTextCellDelegate? 
  32.  
  33. override func awakeFromNib() { 
  34. super.awakeFromNib() 
  35.  
  36. func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) { 
  37. self.dataSource = dataSource 
  38. self.delegate = delegate 
  39.  
  40. label.text = dataSource.title 
  41. switchToggle.on = dataSource.switchOn 
  42. // color option added! 
  43. switchToggle.onTintColor = delegate?.switchColor 
  44.  
  45. @IBAction func onSwitchToggle(sender: UISwitch) { 
  46. delegate?.onSwitchTogleOn(sender.on) 

ViewModel

你現(xiàn)在可以在擴(kuò)展里把數(shù)據(jù)源和delegate邏輯分開了:

  1. import UIKit 
  2.  
  3. struct MinionModeViewModel: SwitchWithTextCellDataSource { 
  4. var title = "Minion Mode!!!" 
  5. var switchOn = true 
  6.  
  7. extension MinionModeViewModel: SwitchWithTextCellDelegate { 
  8.  
  9. func onSwitchTogleOn(on: Bool) { 
  10. if on { 
  11. print("The Minions are here to stay!"
  12. else { 
  13. print("The Minions went out to play!"
  14.  
  15. var switchColor: UIColor { 
  16. return .yellowColor() 

ViewController

這一部分是我不十分確定,ViewController不能傳遞ViewModel兩次:

 

 

 

  1. override func tableView(tableView: UITableView, 
  2. cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
  3. if let setting = Setting(rawValue: indexPath.row) { 
  4. switch setting { 
  5. case .MinionMode: 
  6. let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell 
  7.  
  8. // this is where the magic happens! 
  9. let viewModel = MinionModeViewModel() 
  10. cell.configure(withDataSource: viewModel, delegate: viewModel) 
  11. return cell 
  12.  
  13. return tableView.dequeueReusableCellWithIdentifier("defaultCell", forIndexPath: indexPath) 

代碼已經(jīng)上傳[GitHub]

責(zé)任編輯:chenqingxiang 來源: CocoaChina
相關(guān)推薦

2015-08-04 08:56:14

swift子類

2018-05-10 13:45:15

Swift網(wǎng)絡(luò)層協(xié)議

2018-07-23 15:55:28

協(xié)議自定義viewSwift

2022-04-29 13:43:00

谷歌SWIFT參考架構(gòu)

2015-08-14 11:37:37

Swift語言中文版

2022-07-30 23:41:53

面向過程面向?qū)ο?/a>面向協(xié)議編程

2010-07-09 11:12:09

UDP協(xié)議

2019-02-21 08:30:00

邊緣計(jì)算物聯(lián)網(wǎng)5G

2015-01-29 09:52:43

Swift 開源蘋果

2015-06-23 15:48:41

Swift 2.0iOS9

2024-04-28 10:22:08

.NETMVVM應(yīng)用工具包

2021-08-02 06:49:46

OIDC認(rèn)證協(xié)議

2016-12-12 15:22:41

編程

2010-07-28 09:18:03

Flex2.0

2009-07-24 13:54:39

MVVM模式

2017-07-17 15:19:10

MVVM模式iOS開發(fā)MVP

2018-05-23 16:20:30

IoT協(xié)議思考

2021-06-03 08:55:58

面向協(xié)議編程

2021-06-04 09:01:27

Cocoa 協(xié)議編程 Swift

2015-10-10 09:35:38

swift規(guī)范
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號