背景
我们在做具体业务,特别是复杂页面的时候。经常会遇到各种业务掺杂在一个ViewController的case。比如抖音播放页, 编辑页。此时的ViewController会可能会负责派发业务,缓存状态,导致很多业务都在一个地方交集,理解,维护性很差。
痛点
核心模块耦合过多逻辑。增加各种单一功能变量,代理回调。加重主控制模块压力,而且功能越增加越臃肿。常见于ViewController(我只想安安静静的做点DidLoad, Appear操作)。
常见解决方案
- 分化功能到子view。(缺点:VC需要处理delegate等业务,view交互)
- extensions (缺点:不能添加变量)
- 其他
我们希望可以这样
主控制模块只是负责派发业务,维护状态, 那VC就可以很简洁, 如图:

那就需要支持:
- 模块独立解耦
- 支持同步异步
- 自定义输入输出,自定义变量
- lazy, easy load.
- 异步回调,参数可定制
- 链式调用 继续...
设计
基于Swift语言特性,这里提出一种很简洁的设计方案。
features
- 分化业务
- 自定义输入输出
- 提供回调,自定义返回参
- 支持链式调用(by completion)
- Plugin内部自定义参数
- 生命周期可控
- 无需二次封装
基于此,我们这样设计
Plugin.swift 声明基础协议
public protocol Plugin: class {
associatedtype Input
associatedtype Host
associatedtype Output
init()
func active(in host: Host)
func active(for input: Input, in host: Host)
func active(for input: Input, in host: Host, completion: ((Output) -> ())?)
func deactivate()
}
public extension Plugin {
func active(in host: Host) {}
func active(for input: Input, in host: Host) {}
func active(for input: Input, in host: Host, completion: ((Output) -> ())? = nil) {}
func deactivate() {}
}
PluginManager.swift 插件管理器
internal final class PluginWrapper {
let wrapped: AnyObject
init<P: Plugin>(plugin: P) {
wrapped = plugin
}
}
public final class PluginManager {
private var plugins = [TypeIdentifier: PluginWrapper]()
public init() {
}
public func add<P: Plugin>(_ pluginProvider:@autoclosure () -> P) {
let identifier = TypeIdentifier(type: P.self)
plugins[identifier] = PluginWrapper(plugin: pluginProvider())
}
public func remove<P: Plugin>(type: P.Type) {
let identifier = TypeIdentifier(type: type)
plugins.removeValue(forKey: identifier)
}
public func plugin<P: Plugin>(for type: P.Type) -> P {
if let plugin = plugins[TypeIdentifier(type: type)]?.wrapped as? P {
return plugin
}
let plugin = P()
add(plugin)
return plugin
}
}
private extension PluginManager {
struct TypeIdentifier: Hashable {
private let identifier: ObjectIdentifier
init<T>(type: T.Type) {
identifier = ObjectIdentifier(type)
}
}
}
设计完毕,玩耍起来
public class ViewController: UIViewController {
let pluginMgr = PluginManager()
public override func viewDidLoad() {
super.viewDidLoad()
pluginMgr.plugin(for: GuidePlugin.self).active(in: self)
pluginMgr.plugin(for: TapPlugin.self).active(in: self)
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
pluginMgr.remove(type: GuidePlugin.self)//no need any more
}
func share() {//chain demo
pluginMgr.plugin(LoginPlugin.self).active(for: uid, in: self, completion: {[weak self] success in
if success {
self?.pluginMgr.plugin(CommentPlugin.self).active(in: self)
}
)
}
}
是不是很简单!把基础业务都转交给了具体的插件去做处理。实现了vc的空壳化。而具体插件就可以处理细节性的业务,也可以定制自己的能力。举几个例子:
分享业务
public class SharePlugin: Plugin {
private lazy var shareHandle = ShareHandle()
private var closure: ((ShareResult) -> ())?
public func active(for input: (SharePlatform, [String: Any]), in host: UIViewController, completion: ((ShareResult) -> ())?) {
closure = completion
shareHandle.share(to platform: input.0, params: input.1)
}
}
extension SharePlugin: ShareDelegate {
func shareResult() {
closure?(result)
}
}
引导业务
public class GuidePlugin: Plugin {
let guideView: GuideView?
public func active(in host: UIViewController) {
if !db.KeyExist(key: "guide") {
guideView = GuideView()
host.view.addSubview(guideView!)
}
}
}
总结
设计本身没有性能优缺点。主要为解耦业务,减轻主控制器压力。增删改轻便。 如果有具体设计问题欢迎加q私聊, 371823023. 本人就职抖音,也欢迎各位大佬内推。