国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Swift面向協議編程(POP)的一些Tips

移動開發
協議最常見的用法莫過于進行代理傳值,這就是委托模式。常用的應用場景有:controller中自定義了一個view,view中又添加了一個自定義view。在自定義的view中如果有些函數或者屬性需要到controller中去調用,委托模式的做法就是規定一個協議,讓controller去遵守一個協議并提供實現。

一、委托模式

1、使用過程

協議最常見的用法莫過于進行代理傳值,這就是委托模式。常用的應用場景有:controller中自定義了一個view,view中又添加了一個自定義view。在自定義的view中如果有些函數或者屬性需要到controller中去調用,委托模式的做法就是規定一個協議,讓controller去遵守一個協議并提供實現,那么在自定義view中就能使用協議中的方法。

Swift面向協議編程(POP)的一些Tips

舉個例子,現在想在一個controller中添加一個自定義view,可以實現點擊view中按鈕更改controller中label的值。簡單的代碼如下:

自定義view 

  1. //SelectTabbar.swift 
  2. @objc protocol SelectTabbarDelegate { 
  3.     func changeLabel(_ str: String) 
  4.  
  1. //SelectTabbar.swift 
  2.  class SelectTabbar: UIView { 
  3.     var keywords : [String]? 
  4.     var buttons : [UIButton]? 
  5.     weak public var delegate : SelectTabbarDelegate? 
  6.       
  7.     init(frame: CGRect,keywords:[String]) { 
  8.         super.init(frame: frame) 
  9.         self.keywords = keywords 
  10.         renderView() 
  11.     } 
  12.       
  13.     required init?(coder aDecoder: NSCoder) { 
  14.         fatalError("init(coder:) has not been implemented"
  15.     } 
  16.       
  17.     override func layoutSubviews() { 
  18.         super.layoutSubviews() 
  19.     } 
  20.       
  21.     private func renderView(){ 
  22.         buttons = keywords?.enumerated().map({ (index,key) ->UIButton in 
  23.             let buttonWidth = kScreenWidth/CGFloat((keywords?.count)!) 
  24.             let button = UIButton.init(frame: CGRect.init(x: CGFloat(index)*buttonWidth, y: 0, width: buttonWidth, height: 50)) 
  25.             button.setTitle(keyfor: .normal) 
  26.             button.setTitleColor(UIColor.blue, for: .normal) 
  27.             button.backgroundColor = UIColor.gray 
  28.             button.tag = index 
  29.             button.addTarget(self, action: #selector(tapButton(sender:)), for: .touchUpInside) 
  30.             addSubview(button) 
  31.             return button 
  32.         }) 
  33.     } 
  34.       
  35.     @objc func tapButton(sender: UIButton){ 
  36.         delegate?.changeLabel(keywords![sender.tag]) 
  37.     } 
  38.       

controller: 

  1. class TestViewController: UIViewController,SelectTabbarDelegate { 
  2.     lazy var label : UILabel = { 
  3.         var label = UILabel(frame: CGRect.init(x: 50, y: 200, width: 100, height: 30)) 
  4.         label.text = labelStr 
  5.         label.backgroundColor = UIColor.red 
  6.         return label 
  7.     }() 
  8.       
  9.     private var labelStr : String? { 
  10.         didSet{ 
  11.             label.text = labelStr 
  12.         } 
  13.     } 
  14.       
  15.     override func viewDidLoad() { 
  16.         super.viewDidLoad() 
  17.         view.backgroundColor = .white 
  18.         view.addSubview(label) 
  19.         setupSelectTabbar() 
  20.     } 
  21.       
  22.     func setupSelectTabbar(){ 
  23.         let selectTabbar = SelectTabbar(frame: CGRect.init(x: 0, y: kNavigationHeightAndStatuBarHeight, width: kScreenWidth, height: 50),keywords:["aa","bb"]) 
  24.         selectTabbar.delegate = self 
  25.         view.addSubview(selectTabbar) 
  26.     } 
  27.     func changeLabel(_ str: String) { 
  28.         labelStr = str 
  29.     } 
  30.       

這樣就能比較清楚的表明自己的邏輯。否則,如果要在view操作controller的內容,則需要在外部操作controller的實例,這就造成一個問題,就是無法操作實例中的私有屬性和私有方法(雖然iOS是一門動態語言,不存在絕對的私有,但是誰會去一直去使用runtime來進行操作呢)。

2、注意點

在 ARC 中,對于一般的 delegate,我們會在聲明中將其指定為 weak,在這個 delegate 實際的對象被釋放的時候,會被重置回 nil。這可以保證即使 delegate 已經不存在時,我們也不會由于訪問到已被回收的內存而導致崩潰。ARC 的這個特性杜絕了 Cocoa 開發中一種非常常見的崩潰錯誤,說是救萬千程序員于水火之中也毫不為過。

在 Swift 中我們當然也會希望這么做。但是當我們嘗試書寫這樣的代碼的時候,編譯器不會讓我們通過:

  1. 'weak' cannot be applied to non-class type 

原因:這是因為 Swift 的 protocol 是可以被除了 class 以外的其他類型遵守的,而對于像 struct 或是 enum 這樣的類型,本身就不通過引用計數來管理內存,所以也不可能用 weak 這樣的 ARC 的概念來進行修飾。

兩種解決方法:

  1. 使用@objc
  2. 聲明類類型專屬協議。通過添加 class 關鍵字來限制協議只能被類類型遵循,而結構體或枚舉不能遵循該協議。class 關鍵字必須***個出現在協議的繼承列表中,在其他繼承的協議之前
  • protocol SelectTabbarDelegate : class

二、AOP編程思想的運用

首先我們理解下AOP的含義。

  • In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself, instead separately specifying which code is modified via a “pointcut” specification, such as “log all function calls when the function’s name begins with ‘set’”. This allows behaviors that are not central to the business logic (such as logging) to be added to a program without cluttering the code, core to the functionality. AOP forms a basis for aspect-oriented software development.

在swift簡單來說,就是利用協議去切入某些代碼中,將額外的功能單獨出來而不產生耦合,可以將這些與主邏輯關系不大的代碼統一放到一起。

常用的場景:日志記錄,性能統計,安全控制,事務處理,異常處理等等。

接上面的例子,我們需要在打開TestViewController的時候統計一次,點擊兩個按鈕的時候也進行統計,統計的內容由identifer進行區分。

我們先建立一個Statistician.swift 來存放我們的統計邏輯。(模擬實現)

申明一個StatisticianProtocal協議并提供他的默認實現。 

  1. import Foundation 
  2. enum LogIdentifer:String { 
  3.     case button1 = "button1" 
  4.     case button2 = "button2" 
  5.     case testViewController = "testViewController" 
  6.   
  7. protocol StatisticianProtocal { 
  8.     func statisticianLog(fromClass:AnyObject, identifer:LogIdentifer) 
  9.     func statisticianUpload(fromClass:AnyObject, identifer:LogIdentifer) 
  10.     //用一個尾隨閉包來擴展功能 
  11.     func statisticianExtension(fromClass:AnyObject, identifer:LogIdentifer, extra:()->()) 
  12.   
  13. extension StatisticianProtocal{ 
  14.     func statisticianLog(fromClass:AnyObject, identifer:LogIdentifer) { 
  15.         print("statisticianLog--class:\(fromClass) from:\(identifer.rawValue)"
  16.     } 
  17.       
  18.     func statisticianUpload(fromClass:AnyObject, identifer:LogIdentifer) { 
  19.         print("statisticianUpload--class:\(fromClass) from:\(identifer.rawValue)"
  20.     } 
  21.       
  22.     func statisticianExtension(fromClass:AnyObject, identifer:LogIdentifer, extra:()->()){ 
  23.         extra() 
  24.     } 
  25.   
  26. class Statistician: NSObject { 
  27.   

接下來在任何需要統計的類里面,我們讓這個類去遵守這個協議,然后在需要的地方調用協議中的方法即可。如果在某個特定的類中需要調用的方法略有不同,重寫協議中的方法即可。 

  1. class SelectTabbar: UIView,StatisticianProtocal { 
  2.     var keywords : [String]? 
  3.     var buttons : [UIButton]? 
  4.     weak public var delegate : SelectTabbarDelegate? 
  5.       
  6.     init(frame: CGRect,keywords:[String]) { 
  7.         super.init(frame: frame) 
  8.         self.keywords = keywords 
  9.         renderView() 
  10.         //進行一次統計 
  11.         operateStatistician(identifer: .testViewController) 
  12.     } 
  13.       
  14.     required init?(coder aDecoder: NSCoder) { 
  15.         fatalError("init(coder:) has not been implemented"
  16.     } 
  17.       
  18.       
  19.     override func layoutSubviews() { 
  20.         super.layoutSubviews() 
  21.     } 
  22.       
  23.     private func renderView(){ 
  24.         buttons = keywords?.enumerated().map({ (index,key) ->UIButton in 
  25.             let buttonWidth = kScreenWidth/CGFloat((keywords?.count)!) 
  26.             let button = UIButton.init(frame: CGRect.init(x: CGFloat(index)*buttonWidth, y: 0, width: buttonWidth, height: 50)) 
  27.             button.setTitle(keyfor: .normal) 
  28.             button.setTitleColor(UIColor.blue, for: .normal) 
  29.             button.backgroundColor = UIColor.gray 
  30.             button.tag = index 
  31.             button.addTarget(self, action: #selector(tapButton(sender:)), for: .touchUpInside) 
  32.             addSubview(button) 
  33.             return button 
  34.         }) 
  35.     } 
  36.       
  37.     @objc func tapButton(sender: UIButton){ 
  38.         //進行一次統計 
  39.         switch sender.tag { 
  40.           case 0:operateStatistician(identifer: .button1) 
  41.           default:operateStatistician(identifer: .button2) 
  42.         } 
  43.         delegate?.changeLabel(keywords![sender.tag]) 
  44.     } 
  45.       
  46.     func operateStatistician(identifer:LogIdentifer){ 
  47.         statisticianLog(fromClass: self, identifer: identifer) 
  48.         statisticianUpload(fromClass: self, identifer: identifer) 
  49.         statisticianExtension(fromClass: self, identifer: identifer) { 
  50.             print("extra: in SelectTabbar class"
  51.         } 
  52.     } 
  53.       

以上代碼實現了三處統計的邏輯,而不用把統計的邏輯寫入controller文件中,降低了功能上的耦合度。

三、用來代替extension,增強代碼可讀性

使用擴展,可以很方便的為一些繼承它的子類增添一些函數。這就帶來一個問題,就是所有的子類都擁有了這個方法,但是方法的本身可能不明確,或者是只是想讓少數子類來使用這個方法。這時候可以使用協議來代替extension。 

  1. //定義了一個Shakable協議,遵守這個協議的類即可使用里面的方法,并為該方法提供一個默認的實現 
  2. //where Self:UIView表明了只有uiview的子類可以遵守這個協議 
  3. protocol Shakable { 
  4.     func shakeView() 
  5.   
  6. extension Shakable where Self:UIView{ 
  7.     func shakeView(){ 
  8.         print(Self.self) 
  9.     } 

這時候可以讓某個子類來遵守協議。例如剛才上面的例子。

  1. class SelectTabbar: UIView,Shakable 

如果不在類中重新實現這個方法,則可以實現默認的方法。這個意思表明,SelectTabbar類的子類是遵守Shakable協議的,間接等于SelectTabbar():Shakable?。這樣我們就可以愉快的讓SelectTabbar對象去使用這個方法。(Self關鍵字只能用在協議或者類中,表示當前類,可作為返回值使用)。

一旦不想讓某個子類使用shakeView()方法,很簡單,只要把class SelectTabbar: UIView,Shakable中的Shakable協議干掉即可。

其他實踐:

利用AOP去分離tableview的數據源和事件源的方法,可以單獨處理里面的邏輯,使tableview的代理方法不顯得那么冗余。

總結

關于協議,還有很多種用法。以上是目前比較常用的場景。日后開發中如果發現協議在其他地方中有更好的應該,將會更新本文

 

責任編輯:未麗燕 來源: peipeiblog
相關推薦

2023-10-09 08:14:10

Helm管理應用

2013-07-02 10:18:20

編程編程策略

2013-07-02 09:43:02

編程策略

2010-06-09 17:13:12

IPv6協議路由協議

2021-10-13 07:48:23

Options模式編程

2021-04-09 10:26:43

Python編程技術

2010-08-05 13:54:36

NFS協議

2018-06-08 08:50:35

編程語言并發編程

2011-08-31 10:54:25

Java性能

2011-09-13 09:41:59

Python

2012-04-05 13:24:30

2012-02-16 08:19:03

2016-12-12 15:22:41

編程

2010-09-17 15:41:46

網絡協議分析軟件

2022-07-30 23:41:53

面向過程面向對象面向協議編程

2009-11-23 13:44:33

PHP5面向對象

2015-08-04 08:56:14

swift子類

2015-09-15 10:40:41

Swift2.0MVVM

2015-03-30 11:21:27

編程編程反思

2020-12-04 09:11:45

Python加密文件爆破字典
點贊
收藏

51CTO技術棧公眾號

精品日本美女福利在线观看| 美女午夜精品| 成人免费视频app| 免费成人在线观看av| 黄色网一区二区| 亚洲一区 二区| 一区二区免费在线播放| 亚洲欧美国产一区二区三区| 无码人妻精品一区二区三区99v| 日本女优爱爱视频| 在线播放av更多| 中文字幕免费高清电视剧网站在线观看| 国产午夜一区| 美腿丝袜亚洲综合| 欧美日韩国产一中文字不卡 | 亚洲高清在线免费观看| 午夜精彩视频| 精品国产免费人成网站| 麻豆91在线播放| 高跟丝袜欧美一区| 秋霞成人午夜鲁丝一区二区三区| 国产a级片免费观看| 无码内射中文字幕岛国片| 宅男在线观看免费高清网站| 激情亚洲成人| 337p日本欧洲亚洲大胆色噜噜| 啪一啪鲁一鲁2019在线视频| 欧美一级免费在线观看| 国产精品香蕉| 国产 日韩 欧美大片| 色噜噜狠狠色综合网| 国产精品秘入口| 亚洲va韩国va欧美va精品| 天堂影视av| 一本一道久久a久久精品综合蜜臀| 小香蕉视频在线| 日本黄色一区二区| 超碰电影在线播放| 亚洲精品久久久一区二区三区 | 超碰在线公开97| 在线播放麻豆| 黑人巨大精品欧美一区| 久久99久国产精品黄毛片入口| 亚洲精品少妇久久久久久| 麻豆精品国产| 午夜不卡在线视频| 天堂精品一区二区三区| 精品三级久久久久久久电影聊斋| 日本欧美一区二区三区乱码| 亚洲第一av在线| 国产网站免费在线观看| 日韩精品一区二区三区免费观看| 国产精品污www在线观看| 欧美日韩一区二区三区在线视频| 99视频高清| 久久伊人中文字幕| 男女午夜视频在线观看| 欧美va天堂在线| 久久人人爽爽人人爽人人片av| 美女视频一区在线观看| 亚洲人成无码网站久久99热国产| 最新热久久免费视频| аⅴ资源新版在线天堂| 亚洲激情中文字幕| 女同久久另类99精品国产| 高清av免费一区中文字幕| 久久99精品久久久久久| 国产激情二区| 日韩成人在线网站| 欧美午夜寂寞| 亚洲一区在线免费| 国产女同互慰高潮91漫画| 成av人电影在线观看| 一本久久综合亚洲鲁鲁| 一本到12不卡视频在线dvd| 51xx午夜影福利| 欧美日韩亚洲视频一区| 欧美日韩精品免费观看视欧美高清免费大片| 国产成人精品久久亚洲高清不卡| 天堂一区二区在线免费观看| 日韩av手机版| 亚洲国产天堂久久综合网| 日韩三级毛片| 国产a级黄色大片| 在线精品视频一区二区三四 | 久久久久亚洲精品成人网小说| 伊人久久大香线蕉综合四虎小说 | 色午夜这里只有精品| 亚洲影视一区| 中文字幕一区二区三区四区在线视频 | 日本中文字幕一区二区| 99热在线播放| 久久久美女艺术照精彩视频福利播放| av网站大全在线观看| 久久99精品久久久久久噜噜| 欧美综合二区| 你懂的在线播放| 欧美性在线观看| 国产成人免费视频一区| 午夜激情在线观看| 国产精品久久久久久av福利| 91视频免费看| 在线观看精品| 久久久久久久有限公司| 性感美女久久精品| xxxx日韩| 久久久999视频| 伊人久久久久久久久久久久久| 久久精品电影| 爱久久·www| 99电影在线观看| 午夜精品免费在线观看| 亚洲人成亚洲精品| xx欧美撒尿嘘撒尿xx| 色播久久人人爽人人爽人人片视av| 丝袜美腿亚洲综合| 国产在线高清理伦片a| 国产成人看片| 一本一道久久a久久精品| 成人一二三区| 中文字幕毛片| 国产精品视频白浆免费视频| 亚洲激情一二三区| 精品国产美女| 污导航在线观看| 成人网中文字幕| 色婷婷综合中文久久一本| 久久高清精品| 尤物视频在线观看| 亚洲无av在线中文字幕| 2014亚洲片线观看视频免费| 最新天堂资源在线| 在线播放一区二区三区| 91高清在线观看视频| 亚洲欧美在线x视频| 亚洲欧美视频| 国产在线不卡| 日韩欧美亚洲精品| 欧美色精品在线视频| 久久精品国产亚洲夜色av网站| 香港日本韩国三级网站| 国产综合在线视频| 国产精品日韩成人| 婷婷成人在线| 国产一级黄色片免费| 国产成人综合久久| 亚洲国产乱码最新视频| 日韩午夜电影网| 你懂的在线网址| 久久亚洲国产精品日日av夜夜| 午夜精品久久久| 欧美精品激情| 免费**毛片在线| 亚洲在线视频一区二区| 正在播放欧美一区| 国产欧美日韩久久| 成人激情在线| 国产在线91| 日日夜夜精品网站| 中文字幕亚洲在线| 亚洲免费色视频| 欧美日韩理论| 老色鬼在线视频| 日本国产在线播放| 国产97在线|日韩| 欧美精品丝袜中出| 成人看片黄a免费看在线| 激情小说一区| 日本免费不卡| 亚洲欧洲日夜超级视频| 日韩一级黄色av| 一区二区三区在线影院| 999亚洲国产精| 粉嫩av一区二区三区四区五区| 天天影视色香欲综合网天天录日日录| 日韩免费av一区二区| 欧美日韩综合在线免费观看| 日韩av网站免费在线| 青草综合视频| 在线观看中文字幕| 国产三级中文字幕| 日本精品视频在线播放| 56国语精品自产拍在线观看| 成人激情视频网站| 国产一区二区三区电影在线观看| 影音欧美亚洲| 亚洲色图插插| 僵尸再翻生在线观看免费国语| 99在线视频影院| 青草国产精品| 日韩av网站免费在线| 日韩精品电影| 久久精品毛片| 欧美一级日韩免费不卡| 成人精品视频在线| av一区二区三区四区电影| 国产精品久久久久久久一区探花| 国产日韩欧美亚洲一区| 国产精品扒开做爽爽爽的视频| 久久精品国产99久久|