Swinject容器注册异常:ConnectivityManager的network属性始终为nil
嘿,我来帮你捋捋这个Swinject依赖注入的问题~ 你遇到的情况很典型,ViewController通过storyboardInitCompleted能正常注入,但ConnectivityManager的network始终为nil,大概率是以下几个地方出了问题,咱们一个个排查:
1. 你是不是手动初始化了ConnectivityManager?
这是最容易踩的坑!如果你的代码里是这么写的:
let manager = ConnectivityManager() // 手动new实例
那Swinject根本管不到这个实例,自然不会帮你注入network属性。必须通过Swinject容器的resolve方法获取实例:
let connectivityManager = container.resolve(ConnectivityManager.self)!
2. ConnectivityManager的依赖绑定是否正确?
你需要确保ConnectivityManager的绑定配置里,明确关联了NetworkProtocols的依赖。分两种情况:
情况A:构造函数注入(推荐方式)
如果ConnectivityManager的init方法接收NetworkProtocols参数:
class ConnectivityManager { let network: NetworkProtocols init(network: NetworkProtocols) { self.network = network } }
那绑定的时候要让容器知道怎么传入这个依赖:
// 先注册NetworkProtocols到ApiManager的实现 container.register(NetworkProtocols.self) { _ in ApiManager() } // 再注册ConnectivityManager,通过容器resolve依赖 container.register(ConnectivityManager.self) { resolver in ConnectivityManager(network: resolver.resolve(NetworkProtocols.self)!) }
情况B:属性注入
如果是用属性注入(比如network是var属性),你需要在绑定的时候加上initCompleted闭包,告诉Swinject在实例初始化完成后注入依赖:
class ConnectivityManager { var network: NetworkProtocols? // 注意是var,且可选(或者用隐式解包) } // 绑定配置 container.register(NetworkProtocols.self) { _ in ApiManager() } container.register(ConnectivityManager.self) { _ in ConnectivityManager() } .initCompleted { resolver, manager in manager.network = resolver.resolve(NetworkProtocols.self) }
另外,也可以用Swinject的@Inject属性包装器(需要导入SwinjectAutoregistration):
class ConnectivityManager { @Inject var network: NetworkProtocols }
这种情况下,只要你是通过容器resolve的实例,属性会自动注入,但要确保容器已经注册了NetworkProtocols的实现。
3. 检查NetworkProtocols的注册是否有效
如果NetworkProtocols的注册本身有问题,resolve的时候返回nil,那注入的network自然也是nil。比如有没有写错协议名、ApiManager是否正确实现了NetworkProtocols?
确认你的注册代码是类似这样的:
container.register(NetworkProtocols.self) { _ in ApiManager() } // 如果是单例需求,加上.inObjectScope(.container) // container.register(NetworkProtocols.self) { _ in ApiManager() }.inObjectScope(.container)
4. 检查属性的访问权限
如果ConnectivityManager的network属性是private或者fileprivate,Swinject没有权限给它赋值,会导致注入失败。确保属性的访问权限是internal(默认)或者public:
class ConnectivityManager { // 不要加private! var network: NetworkProtocols? }
5. 是不是ConnectivityManager需要单例?
如果你希望ConnectivityManager是全局单例,记得在绑定的时候设置对象作用域,避免每次resolve都创建新实例,同时确保依赖注入只做一次:
container.register(ConnectivityManager.self) { resolver in ConnectivityManager(network: resolver.resolve(NetworkProtocols.self)!) }.inObjectScope(.container) // 容器级单例,整个容器生命周期内只有一个实例
你可以对照上面的点逐一排查,大概率能找到问题所在~
内容的提问来源于stack exchange,提问作者ironRoei

