当前位置:  开发笔记 > IOS > 正文

Swift:创建一个多功能多播委托

如何解决《Swift:创建一个多功能多播委托》经验,为你挑选了2个好方法。

我想在事情发生变化时使用多播委托通知多个对象.我读过的教程解释了这个,有一个协议,只有一个函数直接在代理数组上调用.当只定义了一个函数时,它工作正常.我的协议有6个功能.我想避免创建6个单独的函数,并重用一个可以应用于我的代理数组的函数.

简单的例子:(我知道这没有用,但我只是想了解我的想法.

protocol MyProtocol {
 func method1()
 func method2()
 func method3()
}


class TestClass {
  var delegates = [MyProtocol]()

  func invokeDelegates(delegateMethod: () -> ()) {
    for delegate in delegates {
      delegate.delegateMethod()
    }
  }
}

显而易见的问题是编译器抱怨原始协议中没有定义"delegateMethod".有没有办法将该方法转换为MyProtocol的一部分,编译器会信任我?

这甚至可能吗?



1> Klemen..:

以下是我在项目中使用的多播委托模式的要点.它还可以防止强大的参考周期(内存泄漏).WeakWrapper处理这个问题.

好.在一些解决方案中,我看到了错误(强大的保留周期,竞争条件......)

以下是我根据1天研究结合的内容.对于代理堆栈,我使用了NSHashTable,因此所有代理都有弱引用.

class MulticastDelegate  {
  private let delegates: NSHashTable = NSHashTable.weakObjects()

  func add(delegate: T) {
    delegates.add(delegate as AnyObject)
  }

  func remove(delegate: T) {
    for oneDelegate in delegates.allObjects.reversed() {
      if oneDelegate === delegate as AnyObject {
        delegates.remove(oneDelegate)
      }
    }
  }

  func invoke(invocation: (T) -> ()) {
    for delegate in delegates.allObjects.reversed() {
      invocation(delegate as! T)
    }
  }
}

func +=  (left: MulticastDelegate, right: T) {
  left.add(delegate: right)
}

func -=  (left: MulticastDelegate, right: T) {
  left.remove(delegate: right)
}



如何设置委托:

object.delegates.add(delegate: self)



如何在委托上执行功能: 而不是

delegate?.delegateFunction

你用

delegates.invoke(invocation: { $0.delegateFunction })



2> rob mayoff..:

您需要更改签名invokeDelegates以获取类型的闭包(MyProtocol) -> (),然后您需要将每个委托传递给闭包.

protocol MyProtocol {
    func method1()
    func method2()
    func method3()
}

class TestClass {
    var delegates = [MyProtocol]()

    func invokeDelegates(delegateMethod: (MyProtocol) -> ()) {
        for delegate in delegates {
            delegateMethod(delegate)
        }
    }
}

闭包应该只在其参数上调用适当的委托方法.Swift可以推断出闭包的参数和返回类型,你可以使用简写$0来引用参数,所以闭包可以很短:

let tester = TestClass()
tester.invokeDelegates(delegateMethod: { $0.method1() })

另一方面,您可以Collection.forEach直接在delegates数组上使用(如果它是可访问的)并跳过该invokeDelegates方法:

tester.delegates.forEach { $0.method1() }

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有