中介者模式
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
下面我通过代买来实现以下中介者
import UIKit
class ViewController: UIViewController {
var fyTimer: Timer?
var fyProxy = FYProxy()
override func viewDidLoad() {
super.viewDidLoad()
fyTimer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
RunLoop.current.add(fyTimer!, forMode: .common)
}
@objc func timerFire() {
print("timer fire")
}
}
先来看上面代码,可能你已经发现了上面代码的问题,是的,循环引用,既然会产生循环引用,那么我们可以通过一些手段解决,比如用block回调,相信用过的都知道怎么用,这里我就不过多介绍。
可不可以将targe转移,把一些target指向self的处理交给中介,来解决这个问题呢?
我这里引入了一个中介者,FYProxy
FYProxy的定义:
import UIKit
class FYProxy: NSObject {
weak var target: NSObjectProtocol?
var sel: Selector?
var fyTimer: Timer? = nil
override init() {
super.init()
}
func fy_scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) {
self.fyTimer = Timer.init(timeInterval: ti, target: self, selector: aSelector, userInfo: userInfo, repeats: yesOrNo);
RunLoop.current.add(self.fyTimer!, forMode: .common)
self.target = (aTarget as! NSObjectProtocol)
self.sel = aSelector
guard self.target?.responds(to: self.sel) == true else {
return
}
let method = class_getInstanceMethod(self.classForCoder, #selector(self.fyTimerFire))
class_replaceMethod(self.classForCoder, self.sel!, method_getImplementation(method!), method_getTypeEncoding(method!))
}
@objc fileprivate func fyTimerFire() {
if let tag = self.target {
tag.perform(self.sel)
} else {
self.fyTimer?.invalidate()
self.fyTimer = nil
}
}
//消息转发
override func forwardingTarget(for aSelector: Selector!) -> Any? {
if self.target?.responds(to: self.sel!) == true {
return self.target
} else {
print("写这样的代码,你想上天?")
return super.forwardingTarget(for: aSelector)
}
}
}
那么在VC中我们就不用这么这么使用了:
import UIKit
class ViewController: UIViewController {
var fyTimer: Timer?
var fyProxy = FYProxy()
override func viewDidLoad() {
super.viewDidLoad()
//循环引用
// fyTimer = Timer.init(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
// RunLoop.current.add(fyTimer!, forMode: .common)
// Timer.init(timeInterval: <#T##TimeInterval#>, target: <#T##Any#>, selector: <#T##Selector#>, userInfo: <#T##Any?#>, repeats: <#T##Bool#>)
// Do any additional setup after loading the view.
// let method = NSSelectorFromString("jjjj")
fyProxy.fy_scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
}
@objc func timerFire() {
print("timer fire")
}
deinit {
print("\(self)走了")
}
}
你可能看着有点懵,我来解释一下上面的代码:
FYProxy类中的target使用weak 修饰 ,这解决了循环引用的问题,
用targer 属性记录传递的target,用sel保存外部方法,
将外部的方法做了一个方法转换,转换为使用自己的方法
在自己的方法中在使用targer去调用 sel,如果target销毁了,那么终止计时器相应
此时此刻,完美,这无敌的操作。
网友评论