最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2018年10月21日 14:30:40   作者:Dariel  
這篇文章主要給大家介紹了關于iOS中多繼承與多重代理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

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

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

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

1. 多繼承

1. 實現過程

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

多繼承的實現:協議的方法可以在該協議的extension中實現

protocol Behavior {
 func run()
}
extension Behavior {
 func run() {
  print("Running...")
 }
}

struct Dog: Behavior {}

let myDog = Dog()
myDog.run() // Running...

無論是結構體還是類還是枚舉都可以遵守多個協議,所以要實現多繼承,無非就是多遵守幾個協議的問題.

下面舉個例子.

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協議就可以啦!

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都有一個默認的實現方法method(),由于編譯器不知道繼承過來的method()方法是哪個,就會報錯.

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

解決方法:

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

2. 直接修改協議中重復的方法.

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

2. 多重代理

1. 多重代理的實現過程

我們以一個代理的經典問題來表述:

主人叫寵物們去吃飯,吃這個動作作為一個協議,我們要做到統(tǒng)一管理.

1. 定義協議

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

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

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

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

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

class masterOrderDelegateManager : MasterOrderDelegate {
  private let multiDelegate: NSHashTable<AnyObject> = NSHashTable.weakObjects()

  init(_ delegates: [MasterOrderDelegate]) {
    delegates.forEach(multiDelegate.add)
  }
  
  // 協議中的方法,可以有多個
  func toEat(_ food: String) {
    invoke { $0.toEat(food) }
  }
  
  // 添加遵守協議的類
  func add(_ delegate: MasterOrderDelegate) {
    multiDelegate.add(delegate)
  }
  
  // 刪除指定遵守協議的類
  func remove(_ delegateToRemove: MasterOrderDelegate) {
    invoke {
      if $0 === delegateToRemove as AnyObject {
        multiDelegate.remove($0)
      }
    }
  }
  
  // 刪除所有遵守協議的類
  func removeAll() {
    multiDelegate.removeAllObjects()
  }

  // 遍歷所有遵守協議的類
  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])
// 添加遵守該協議的類
delegate.add(cat1)
// 刪除遵守該協議的類
delegate.remove(dog)

master.delegate = delegate
master.orderToEat()

// 輸出
// Cat is eating meat
// Cat is eating meat

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

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

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • xcode 4 制作靜態(tài)庫圖文詳解

    xcode 4 制作靜態(tài)庫圖文詳解

    我這個文檔的靜態(tài)庫的開發(fā)是基于Xcode4.2和iOS SDK5.0編寫的。Xcode4跟之前的Xcode3還是有不少的差別的
    2013-06-06
  • iOS開發(fā)之事件傳遞響應鏈

    iOS開發(fā)之事件傳遞響應鏈

    這篇文章主要為大家介紹了iOS開發(fā)之事件傳遞響應鏈,何為事件的響應鏈,本文為大家揭曉,感興趣的小伙伴們可以參考一下
    2016-01-01
  • iOS新版微信底部返回橫條問題的解決

    iOS新版微信底部返回橫條問題的解決

    這篇文章主要介紹了iOS新版微信底部返回橫條問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • iOS中讀寫鎖的簡單實現方法實例

    iOS中讀寫鎖的簡單實現方法實例

    讀寫鎖是計算機程序的并發(fā)控制的一種同步機制,也稱“共享-互斥鎖”、多讀者-單寫者鎖,讀操作可并發(fā)重入,寫操作是互斥的,這篇文章主要給大家介紹了關于iOS中讀寫鎖的簡單實現方法,需要的朋友可以參考下
    2021-11-11
  • iOS左滑手勢失效的解決方法

    iOS左滑手勢失效的解決方法

    這篇文章主要為大家詳細介紹了iOS左滑手勢失效的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • iOS中常用設置返回按鈕

    iOS中常用設置返回按鈕

    本文給大家分享一段代碼關于iOS中常用設置返回按鈕的實現方法,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下
    2016-12-12
  • Objective-C中關于實例所占內存的大小詳解

    Objective-C中關于實例所占內存的大小詳解

    這篇文章主要給大家介紹了關于Objective-C中實例所占內存的大小的相關資料,文中通過示例代碼介紹的非常詳細,對各位iOS開發(fā)者們具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-05-05
  • iOS 二維碼掃描和應用跳轉

    iOS 二維碼掃描和應用跳轉

    本文講解如何使用原生框架實現二維碼掃描功能,并且進行掃描后的項目跳轉。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-03-03
  • iOS開發(fā)中用imageIO漸進加載圖片及獲取exif的方法

    iOS開發(fā)中用imageIO漸進加載圖片及獲取exif的方法

    這篇文章主要介紹了iOS開發(fā)中中用imageIO漸進加載圖片及獲取exif的方法,代碼演示為傳統(tǒng)的Objective-C,需要的朋友可以參考下
    2015-09-09
  • iOS中設置view圓角化的四種方法示例

    iOS中設置view圓角化的四種方法示例

    最近因為工作的原因,遇到view圓角優(yōu)化的問題,所以將實現的幾種方法總結分享出來,下面這篇文章主要給大家介紹了關于iOS中設置view圓角化的四種方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧。
    2017-09-09

最新評論

荔浦县| 布尔津县| 德江县| 白河县| 阿鲁科尔沁旗| 柏乡县| 衡阳市| 雷波县| 商水县| 青浦区| 沅陵县| 青铜峡市| 额尔古纳市| 信丰县| 邻水| 遵化市| 太仆寺旗| 剑川县| 永丰县| 彩票| 泸定县| 普格县| 扬州市| 二连浩特市| 平顶山市| 龙井市| 漾濞| 临猗县| 临猗县| 宁陕县| 年辖:市辖区| 大城县| 龙陵县| 靖江市| 林芝县| 阿拉善盟| 五寨县| 灵丘县| 贵德县| 莱芜市| 两当县|