Swift中如何让B类调用委托A类所持C类实例的方法?
解决Class B调用Class A所持Class C实例方法的几种方案
我来帮你梳理几个Swift里常用的解决方案,都是针对这种委托链调用的场景:
方案1:修改协议,通过委托转发调用
这是最贴合原有委托设计思路的方案,我们可以调整ClassBDelegate协议,要么让它提供访问ClassC的入口,要么直接定义需要调用的方法,让ClassA内部转发给ClassC。
子方案1a:协议暴露ClassC实例
如果允许ClassB知晓ClassC的存在,可以让协议返回ClassC实例:
// 调整协议,添加获取ClassC的只读属性 protocol ClassBDelegate: class { var classC: ClassC { get } } class ClassC { func myFunc() { print("执行ClassC的myFunc方法") } } class ClassA: ClassBDelegate { // ClassA持有ClassC实例 private let classCInstance = ClassC() // 实现协议要求的属性,返回内部的ClassC实例 var classC: ClassC { return classCInstance } } class ClassB { weak var delegate: ClassBDelegate? func triggerAction() { // 现在可以通过协议拿到ClassC实例,再调用目标方法 delegate?.classC.myFunc() } }
子方案1b:协议直接定义方法,由ClassA转发
如果想降低耦合,不让ClassB知道ClassC的存在,可以直接把myFunc放到协议里,让ClassA实现时内部转发:
protocol ClassBDelegate: class { func myFunc() // 直接把需要调用的方法定义在协议中 } class ClassA: ClassBDelegate { private let classCInstance = ClassC() // 实现协议方法,内部转发给ClassC的对应方法 func myFunc() { classCInstance.myFunc() } } class ClassB { weak var delegate: ClassBDelegate? func triggerAction() { // 和原来的调用方式完全一致,不用修改ClassB的调用逻辑 delegate?.myFunc() } }
这个方式更推荐,因为ClassB只依赖抽象的协议,完全不需要关心ClassC的存在,符合面向抽象编程的原则。
方案2:用闭包替代委托(适合单一方法场景)
如果只是需要调用这一个方法,不想修改协议,可以给ClassB添加一个闭包属性,让ClassA初始化时把ClassC的方法绑定进去:
class ClassB { // 定义一个和myFunc签名一致的闭包属性 var onMyFuncTriggered: (() -> Void)? func triggerAction() { // 直接调用闭包 onMyFuncTriggered?() } } class ClassA { private let classCInstance = ClassC() let classB = ClassB() init() { // 绑定闭包,注意用[weak self]避免循环引用 classB.onMyFuncTriggered = { [weak self] in self?.classCInstance.myFunc() } } }
这个方案更轻量,不需要维护协议,但如果后续需要多个方法,会导致ClassB里的闭包属性越来越多,代码变得杂乱。
方案3:让ClassC直接作为ClassB的委托(谨慎使用)
如果业务逻辑允许,也可以跳过ClassA,直接让ClassC实现ClassBDelegate协议,然后把ClassC实例设为ClassB的delegate。但这种方式只适合ClassC和ClassB的逻辑直接相关的场景,否则会破坏原有的代码结构,增加耦合度。
内容的提问来源于stack exchange,提问作者Chewie The Chorkie
相关产品推荐
相关产品推荐

