我们有一个Base组件,其中包含BaseVC,但是BaseVC中有很多业务逻辑,这些业务逻辑原本在Common中,现在由于依赖关系(Common依赖Base,而Base不能依赖Common)无法直接使用。
解决方案:
- 将BaseVC中的业务逻辑抽离出来,放到Common中,BaseVC只保留非常基础的功能(比如生命周期管理、基础UI配置等)。
- 如果有些业务逻辑确实与BaseVC紧密相关,且不能放到Common中,那么我们可以考虑使用依赖注入或者协议的方式来解耦。
但是,现在的问题是Base组件不能依赖Common,而Common依赖Base。所以,我们可以在Base中定义协议,然后在Common中实现这些协议,并通过依赖注入的方式将实现注入到Base中。
具体步骤:
方案一:抽离业务逻辑
- 将BaseVC中涉及业务逻辑的代码移到Common中的某个类中,然后在BaseVC中通过属性持有这个类的实例,并在需要的时候调用。这样,BaseVC就只依赖一个抽象的协议,而具体的实现由Common提供。
方案二:使用协议和依赖注入
- 在Base中定义业务逻辑需要的协议。
- 在Common中实现这些协议。
- 在App启动时,将协议的实现实例注入到BaseVC中(或者通过ServiceLocator模式、依赖注入容器等方式)。
下面我们以方案二为例,给出一个具体的例子:
假设BaseVC中需要处理用户登录状态,原本直接使用了Common中的UserManager,现在我们要解耦。
步骤1:在Base中定义协议
swift
// Base组件中
public protocol UserManagerProtocol: AnyObject {
var isLoggedIn: Bool { get }
func login()
func logout()
}
步骤2:在BaseVC中持有协议类型的属性
swift
// Base组件中
open class BaseVC: UIViewController {
// 通过依赖注入,默认可以通过ServiceLocator获取,或者由子类设置
public var userManager: UserManagerProtocol?
open func checkLogin() -> Bool {
return userManager?.isLoggedIn ?? false
}
}
步骤3:在Common中实现协议
swift
// Common组件中
import Base
public class UserManager: UserManagerProtocol {
public static let shared = UserManager()
public var isLoggedIn: Bool {
// 返回登录状态
return true
}
public func login() {
// 登录逻辑
}
public func logout() {
// 退出逻辑
}
}
步骤4:在App启动时,设置BaseVC的默认userManager
我们可以在AppDelegate中,或者Common组件中提供一个设置方法,将UserManager.shared赋值给BaseVC的userManager。但是注意,BaseVC的userManager是可选类型,我们需要在合适的地方注入。
我们可以通过方法交换或基类初始化方法来实现,但方法交换不太安全。我们可以在BaseVC中提供一个类方法用来设置默认的UserManager。
或者,我们可以在Common组件中创建一个设置函数,在App启动时调用:
swift
// Common组件中
public func setupBaseVC() {
BaseVC.globalUserManager = UserManager.shared
}
// Base组件中
open class BaseVC: UIViewController {
public static var globalUserManager: UserManagerProtocol?
public var userManager: UserManagerProtocol? {
get {
return _userManager ?? BaseVC.globalUserManager
}
set {
_userManager = newValue
}
}
private var _userManager: UserManagerProtocol?
}
这样,如果没有单独设置,就会使用全局的globalUserManager。
方案三:使用服务发现(Service Locator)模式
我们可以在Base组件中创建一个服务定位器,然后在Common组件中注册服务。
步骤1:在Base组件中创建服务定位器
swift
// Base组件中
public class ServiceLocator {
public static let shared = ServiceLocator()
private var services: [String: Any] = [:]
public func register<Service>(_ service: Service, for type: Service.Type) {
services[String(describing: type)] = service
}
public func resolve<Service>(_ type: Service.Type) -> Service? {
return services[String(describing: type)] as? Service
}
}
步骤2:在BaseVC中通过服务定位器获取服务
swift
// Base组件中
open class BaseVC: UIViewController {
public var userManager: UserManagerProtocol? {
return ServiceLocator.shared.resolve(UserManagerProtocol.self)
}
}
步骤3:在Common组件中注册服务
swift
// Common组件中
import Base
public class UserManager: UserManagerProtocol {
// ... 实现
}
// 在App启动时注册
ServiceLocator.shared.register(UserManager.shared, for: UserManagerProtocol.self)
以上三种方案,我们可以根据实际情况选择。
另外,如果BaseVC中的业务逻辑非常多,我们可能需要考虑重构,将业务逻辑抽离到单独的类中,BaseVC只负责视图生命周期和基础UI,业务逻辑通过依赖注入的方式引入。
最后,我们还可以考虑将Base组件拆分为两个组件:BaseCore和BaseUI。BaseCore包含一些最基础的协议和工具,BaseUI包含BaseVC等UI基类,这样Common可以依赖BaseCore,而BaseUI依赖Common(或者通过协议解耦)。但是这样可能会增加组件数量,需要根据项目情况权衡。
由于时间关系,这里只提供了几种思路和示例代码,具体实施需要根据项目结构进行调整。
你遇到的这个问题很典型:BaseVC 放在基础组件中,但包含了很多业务逻辑,又不能依赖 Common。我来提供几种解决方案:
方案一:依赖注入 + 协议抽象(推荐)
1. 在 Base 组件中定义协议
swift
// Base/Protocols/BusinessProtocols.swift
public protocol UserInfoProvider {
var currentUser: User? { get }
func updateUserInfo(_ user: User)
}
public protocol CacheProvider {
func getCachedData(for key: String) -> Any?
func setCachedData(_ data: Any?, for key: String)
}
public protocol NetworkProvider {
func request(_ endpoint: String, completion: @escaping (Result<Data, Error>) -> Void)
}
2. BaseVC 通过协议使用业务功能
swift
// Base/Classes/BaseViewController.swift
open class BaseViewController: UIViewController {
// 通过协议引用业务功能,不依赖具体实现
public weak var userInfoProvider: UserInfoProvider?
public weak var cacheProvider: CacheProvider?
public weak var networkProvider: NetworkProvider?
// 提供默认空实现,避免崩溃
open var currentUser: User? {
return userInfoProvider?.currentUser
}
open func showUserProfile() {
guard let user = currentUser else {
// 处理未登录情况
showLogin()
return
}
// 显示用户信息
}
open func cacheData(_ data: Any?, for key: String) {
cacheProvider?.setCachedData(data, for: key)
}
open func requestData(_ endpoint: String, completion: @escaping (Result<Data, Error>) -> Void) {
networkProvider?.request(endpoint, completion: completion)
}
// 需要子类重写的方法
open func showLogin() {
// 基类空实现,由业务VC重写
}
}
3. 在 Common 中实现协议
swift
// Common/Classes/ProtocolImplementations.swift
public class CommonUserInfoProvider: UserInfoProvider {
public var currentUser: User? {
return UserManager.shared.currentUser
}
public func updateUserInfo(_ user: User) {
UserManager.shared.updateUser(user)
}
}
public class CommonCacheProvider: CacheProvider {
public func getCachedData(for key: String) -> Any? {
return CacheManager.shared.object(forKey: key)
}
public func setCachedData(_ data: Any?, for key: String) {
CacheManager.shared.setObject(data, forKey: key)
}
}
4. 在 App 启动时注入依赖
swift
// AppDelegate 或专门的配置类
class AppDependencyConfigurator {
static func configure() {
let baseVC = BaseViewController.appearance()
// 注入 Common 中的具体实现
baseVC.userInfoProvider = CommonUserInfoProvider()
baseVC.cacheProvider = CommonCacheProvider()
baseVC.networkProvider = CommonNetworkProvider()
}
}
方案二:模板方法模式
1. BaseVC 定义抽象方法
swift
// Base/Classes/BaseViewController.swift
open class BaseViewController: UIViewController {
// 模板方法 - 具体实现在子类中
open func getCurrentUser() -> User? {
fatalError("子类必须重写此方法")
}
open func cacheData(_ data: Any?, for key: String) {
fatalError("子类必须重写此方法")
}
open func getCachedData(for key: String) -> Any? {
fatalError("子类必须重写此方法")
}
// 具体方法 - 使用抽象方法
open func refreshUserData() {
guard let user = getCurrentUser() else {
showLogin()
return
}
// 使用用户数据
}
}
2. 在 Common 中创建业务基类
swift
// Common/Classes/CommonBaseViewController.swift
open class CommonBaseViewController: BaseViewController {
// 实现 BaseVC 的抽象方法
open override func getCurrentUser() -> User? {
return UserManager.shared.currentUser
}
open override func cacheData(_ data: Any?, for key: String) {
CacheManager.shared.setObject(data, forKey: key)
}
open override func getCachedData(for key: String) -> Any? {
return CacheManager.shared.object(forKey: key)
}
// 业务特定的方法
open func commonBusinessMethod() {
// 使用 Common 中的功能
}
}
方案三:事件总线通信
1. 在 Base 中定义事件系统
swift
// Base/Classes/EventBus.swift
public class EventBus {
public static let shared = EventBus()
private var observers: [String: [(Any?) -> Void]] = [:]
public func publish(_ event: String, data: Any? = nil) {
observers[event]?.forEach { $0(data) }
}
public func subscribe(_ event: String, handler: @escaping (Any?) -> Void) {
if observers[event] == nil {
observers[event] = []
}
observers[event]?.append(handler)
}
}
// Base/Classes/Events.swift
public struct BaseEvents {
public static let getUserInfo = "base.get_user_info"
public static let cacheData = "base.cache_data"
public static let getCachedData = "base.get_cached_data"
}
2. BaseVC 通过事件获取数据
swift
// Base/Classes/BaseViewController.swift
open class BaseViewController: UIViewController {
open func getCurrentUser() -> User? {
var result: User?
let semaphore = DispatchSemaphore(value: 0)
EventBus.shared.subscribe(BaseEvents.getUserInfo) { data in
result = data as? User
semaphore.signal()
}
EventBus.shared.publish(BaseEvents.getUserInfo)
_ = semaphore.wait(timeout: .now() + 1.0)
return result
}
}
3. Common 中监听并响应事件
swift
// Common/Classes/EventHandlers.swift
public class CommonEventHandlers {
public static func setup() {
// 响应获取用户信息事件
EventBus.shared.subscribe(BaseEvents.getUserInfo) { _ in
let user = UserManager.shared.currentUser
EventBus.shared.publish(BaseEvents.getUserInfo, data: user)
}
// 响应缓存事件
EventBus.shared.subscribe(BaseEvents.cacheData) { data in
if let dict = data as? [String: Any],
let key = dict["key"] as? String {
CacheManager.shared.setObject(dict["value"], forKey: key)
}
}
}
}
方案四:服务定位器模式
1. Base 中定义服务定位器
swift
// Base/Classes/ServiceLocator.swift
public class ServiceLocator {
public static let shared = ServiceLocator()
private var services: [String: Any] = [:]
public func register<Service>(_ service: Service, for type: Service.Type) {
services[String(describing: type)] = service
}
public func service<Service>(for type: Service.Type) -> Service? {
return services[String(describing: type)] as? Service
}
}
// Base/Classes/Services.swift
public protocol UserService {
var currentUser: User? { get }
func updateUser(_ user: User)
}
public protocol CacheService {
func setObject(_ object: Any?, forKey key: String)
func object(forKey key: String) -> Any?
}
2. BaseVC 通过服务定位器获取服务
swift
// Base/Classes/BaseViewController.swift
open class BaseViewController: UIViewController {
open var userService: UserService? {
return ServiceLocator.shared.service(for: UserService.self)
}
open var cacheService: CacheService? {
return ServiceLocator.shared.service(for: CacheService.self)
}
open func businessMethod() {
if let user = userService?.currentUser {
// 使用用户数据
}
}
}
3. Common 中注册服务实现
swift
// Common/Classes/ServiceImplementations.swift
public class CommonUserService: UserService {
public var currentUser: User? {
return UserManager.shared.currentUser
}
public func updateUser(_ user: User) {
UserManager.shared.updateUser(user)
}
}
// 在 App 启动时注册
ServiceLocator.shared.register(CommonUserService(), for: UserService.self)