iOS组件化方案

80 阅读3分钟

1. URL Scheme

实现方式

URL Scheme 是一种可以通过URL来调起其他应用或执行特定操作的机制。在iOS中,我们可以利用URL Scheme实现组件化。

  1. 首先,在每个需要被其他模块调用的模块中,注册该模块的URL Scheme。
// 模块A
func registerURLScheme() {
    let urlScheme = "moduleA"
    if let urlTypes = Bundle.main.object(forInfoDictionaryKey: "CFBundleURLTypes") as? [[String: Any]] {
        for urlType in urlTypes {
            if let schemes = urlType["CFBundleURLSchemes"] as? [String],
               let bundleID = Bundle.main.bundleIdentifier,
               schemes.contains(urlScheme) {
                UIApplication.shared.registerURLScheme(urlScheme, forBundleIdentifier: bundleID)
                break
            }
        }
    }
}
  1. 接下来,定义模块A可被调用的操作,并在AppDelegate中进行响应。
// AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    if url.scheme == "moduleA" {
        // 解析URL,执行对应操作
        // ...
        return true
    }
    return false
}
  1. 在其他模块中,通过URL Scheme调起模块A。
if let url = URL(string: "moduleA://action") {
    if UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
}

优点

  • 简单易用,无需引入第三方库或框架。
  • 解耦明显,模块间可以通过URL Scheme进行相互调用。

缺点

  • 不支持类型安全的参数传递。
  • 扩展性有限,URL Scheme只支持简单的模块调用,不适合复杂场景。

2. Protocol Class

实现方式

Protocol Class 是一种基于协议和类的方式实现组件化。通过定义公共协议和实现该协议的类,各个模块可以通过协议来进行通信。

  1. 定义公共协议,例如:
protocol ModuleProtocol {
    func doSomething()
}
  1. 在模块A中实现该协议:
class ModuleA: ModuleProtocol {
    func doSomething() {
        // 实现具体的操作
    }
}
  1. 在其他模块中,通过协议来调用模块A:
var module: ModuleProtocol?

// 注册模块A
func registerModuleA(_ moduleA: ModuleProtocol) {
    self.module = moduleA
}

// 调用模块A的方法
module?.doSomething()

优点

  • 支持类型安全的参数传递。
  • 模块之间通过协议进行通信,解耦明显。

缺点

  • 需要手动注册模块,对代码有一定侵入性。
  • 在项目较大时,需要管理多个模块和协议。

3. Target-Action

实现方式

Target-Action 是一种基于Selector的方式实现组件化。通过定义公共的Selector来实现模块之间的通信。

  1. 在一个公共类中定义Selector,例如:
class ModuleActions: NSObject {
    @objc static func doSomething() {
        // 实现具体的操作
    }
}
  1. 在模块A中,注册该Selector并提供执行方法:
class ModuleA {
    func registerActions() {
        let action = #selector(ModuleActions.doSomething)
        NotificationCenter.default.addObserver(self, selector: action, name: .moduleDoSomething, object: nil)
    }

    func performAction() {
        NotificationCenter.default.post(name: .moduleDoSomething, object: nil)
    }
}
  1. 在其他模块中,通过通知中心来调用对应的Selector:
NotificationCenter.default.addObserver(self, selector: #selector(handleAction), name: .moduleDoSomething, object: nil)

@objc func handleAction() {
    // 处理模块A的动作
}

优点

  • 灵活性高,支持多种类型的参数传递。
  • 模块之间解耦,通过中间件(通知中心)进行通信。

缺点

  • 需要手动注册Selector,对代码有一定侵入性。
  • 模块数量增多时,需要统一管理和命名通知。

总结思考

  • 组件化可以将大型iOS项目拆分成多个独立模块,提高代码可维护性和复用性。
  • 在选择组件化方案时,需要考虑项目的规模、复杂度和团队的技术水平。
  • URL Scheme简单易用,适合简单的模块调用;Protocol Class和Target-Action适合解耦和类型安全传递参数的场景。
  • 组件化方案不是银弹,需要根据实际情况做权衡和选择。