国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > iOS > 正文

談談iOS中的多繼承與多重代理

2020-07-26 02:23:00
字體:
供稿:網(wǎng)友

前言

多繼承和多重代理在swift的語言層面上是不支持的,但我們有時會遇到這樣的問題:

  • 類B和C分別繼承自A,B1和B2繼承自B,C1和C2繼承自C.現(xiàn)在我們需要在B1和C1中添加相同的方法,怎么去做?使用繼承的話只能在類A中添加,但這樣做的結(jié)果是基類A會越來越臃腫,最后變成上帝類God Class,維護起來會很困難.
  • 在實現(xiàn)完某個代理后發(fā)現(xiàn),我們還要在其他頁面中獲取數(shù)據(jù).例如,IM消息接收之后要在多個地方做回調(diào),比如顯示消息內(nèi)容頁面,改變小紅點,顯示消息數(shù).即一對多的模式,我們第一反應是用通知,但通知還是能少用就少用,用多了代碼的可閱讀性會大大降低.

面對第一種情況,最好的解決方法是,B1和C1的公共方法專門封裝到一個地方,需要的時候就調(diào)用一下,多繼承就是一個最好的解決方案.

1. 多繼承

1. 實現(xiàn)過程

swift中的類可以遵守多個協(xié)議,但是只可以繼承一個類,而值類型(結(jié)構(gòu)體和枚舉)只能遵守單個或多個協(xié)議,不能做繼承操作.

多繼承的實現(xiàn):協(xié)議的方法可以在該協(xié)議的extension中實現(xiàn)

protocol Behavior { func run()}extension Behavior { func run() {  print("Running...") }}struct Dog: Behavior {}let myDog = Dog()myDog.run() // Running...

無論是結(jié)構(gòu)體還是類還是枚舉都可以遵守多個協(xié)議,所以要實現(xiàn)多繼承,無非就是多遵守幾個協(xié)議的問題.

下面舉個例子.

2. 通過多繼承為UIView擴展方法

// MARK: - 閃爍功能protocol Blinkable { func blink()}extension Blinkable where Self: UIView { func blink() {  alpha = 1    UIView.animate(   withDuration: 0.5,   delay: 0.25,   options: [.repeat, .autoreverse],   animations: {    self.alpha = 0  }) }}// MARK: - 放大和縮小protocol Scalable { func scale()}extension Scalable where Self: UIView { func scale() {  transform = .identity    UIView.animate(   withDuration: 0.5,   delay: 0.25,   options: [.repeat, .autoreverse],   animations: {    self.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)  }) }}// MARK: - 添加圓角protocol CornersRoundable { func roundCorners()}extension CornersRoundable where Self: UIView { func roundCorners() {  layer.cornerRadius = bounds.width * 0.1  layer.masksToBounds = true }}extension UIView: Scalable, Blinkable, CornersRoundable {} cyanView.blink() cyanView.scale() cyanView.roundCorners()


這樣,如果我們自定義了其他View,只需要放大和縮小效果,遵守Scalable協(xié)議就可以啦!

3. 多繼承鉆石問題(Diamond Problem),及解決辦法

請看下面代碼

protocol ProtocolA {  func method()}extension ProtocolA {  func method() {    print("Method from ProtocolA")  }}protocol ProtocolB {  func method()}extension ProtocolB {  func method() {    print("Method from ProtocolB")  }}class MyClass: ProtocolA, ProtocolB {}

此時ProtocolA和ProtocolB都有一個默認的實現(xiàn)方法method(),由于編譯器不知道繼承過來的method()方法是哪個,就會報錯.

💎鉆石問題Diamond Problem,當某一個類或值類型在繼承圖譜中有多條路徑時就會發(fā)生.

解決方法:

1. 在目標值類型或類中重寫那個發(fā)生沖突的方法method().

2. 直接修改協(xié)議中重復的方法.

文章開頭我們提到的問題2,我們可以試著用多重代理去解決這個問題.

2. 多重代理

1. 多重代理的實現(xiàn)過程

我們以一個代理的經(jīng)典問題來表述:

主人叫寵物們?nèi)コ燥?吃這個動作作為一個協(xié)議,我們要做到統(tǒng)一管理.

1. 定義協(xié)議

protocol MasterOrderDelegate: class {  func toEat(_ food: String)}

2. 定義一個類: 用來管理遵守協(xié)議的類

這邊用了NSHashTable來存儲遵守協(xié)議的類,NSHashTable和NSSet類似,但又有所不同,總的來說有這幾個特點:

1. NSHashTable中的元素可以通過Hashable協(xié)議來判斷是否相等.

2. NSHashTable中的元素如果是弱引用,對象銷毀后會被移除,可以避免循環(huán)引用.

class masterOrderDelegateManager : MasterOrderDelegate {  private let multiDelegate: NSHashTable<AnyObject> = NSHashTable.weakObjects()  init(_ delegates: [MasterOrderDelegate]) {    delegates.forEach(multiDelegate.add)  }    // 協(xié)議中的方法,可以有多個  func toEat(_ food: String) {    invoke { $0.toEat(food) }  }    // 添加遵守協(xié)議的類  func add(_ delegate: MasterOrderDelegate) {    multiDelegate.add(delegate)  }    // 刪除指定遵守協(xié)議的類  func remove(_ delegateToRemove: MasterOrderDelegate) {    invoke {      if $0 === delegateToRemove as AnyObject {        multiDelegate.remove($0)      }    }  }    // 刪除所有遵守協(xié)議的類  func removeAll() {    multiDelegate.removeAllObjects()  }  // 遍歷所有遵守協(xié)議的類  private func invoke(_ invocation: (MasterOrderDelegate) -> Void) {    for delegate in multiDelegate.allObjects.reversed() {      invocation(delegate as! MasterOrderDelegate)    }  }}

3. 其余部分

class Master {  weak var delegate: MasterOrderDelegate?  func orderToEat() {    delegate?.toEat("meat")  }}class Dog {}extension Dog: MasterOrderDelegate {  func toEat(_ food: String) {    print("/(type(of: self)) is eating /(food)")  }}class Cat {}extension Cat: MasterOrderDelegate {  func toEat(_ food: String) {    print("/(type(of: self)) is eating /(food)")  }}let cat = Cat()let dog = Dog()let cat1 = Cat()let master = Master()// master的delegate是弱引用,所以不能直接賦值let delegate = masterOrderDelegateManager([cat, dog])// 添加遵守該協(xié)議的類delegate.add(cat1)// 刪除遵守該協(xié)議的類delegate.remove(dog)master.delegate = delegatemaster.orderToEat()// 輸出// Cat is eating meat// Cat is eating meat

設置masterOrderDelegateManager的好處是,可以通過一個數(shù)組來管理多重代理.

更多iOS相關(guān)知識點歡迎關(guān)注我的Github: SwiftTips (本地下載)

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網(wǎng)的支持。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 买车| 佛学| 双鸭山市| 平罗县| 塔城市| 泰顺县| 邵阳县| 始兴县| 宝坻区| 洞头县| 阿城市| 永康市| 涡阳县| 普兰店市| 分宜县| 孟津县| 丹东市| 喀什市| 哈巴河县| 延川县| 七台河市| 延津县| 阳信县| 文化| 武宁县| 宿迁市| 海原县| 汉沽区| 怀仁县| 博湖县| 汉中市| 丹江口市| 林周县| 华容县| 天峻县| 通河县| 通榆县| 民县| 永春县| 宁波市| 克拉玛依市|