3

我在我的 Swift iOS 应用程序中使用 Swinject 并尝试按照官方文档页面中的说明进行循环依赖:https ://github.com/Swinject/Swinject/blob/master/Documentation/CircularDependencies.md

我从循环依赖示例中复制了代码,并在类中添加了一些东西,没有修改依赖注册代码中的任何内容。

类和协议如下所示:

protocol ParentType: AnyObject {
    func getMyName() -> String
    func getMyChildName() -> String
}

protocol ChildType: AnyObject {
    func getMyName() -> String
    func getMyParentName() -> String
}

class Parent: ParentType {
    let child: ChildType?
    let name = "John"

    init(child: ChildType?) {
        self.child = child
    }

    func getMyName() -> String {
        return name
    }

    func getMyChildName() -> String {
        return child!.getMyName()
    }
}

class Child: ChildType {
    weak var parent: ParentType?
    let name = "John Jr."

    func getMyName() -> String {
        return name
    }

    func getMyParentName() -> String {
        return parent!.getMyName()
    }
}

依赖配置代码如下所示(与示例相同):

let container = Container()
container.register(ParentType.self) { r in
    Parent(child: r.resolve(ChildType.self)!)
}
container.register(ChildType.self) { _ in Child() }
    .initCompleted { r, c in
        let child = c as! Child
        child.parent = r.resolve(ParentType.self)
}

上面的代码在我的 AppDelegate 的 " application:didFinishLaunchingWithOptions" 函数中。在注册码之后,我添加了这个小测试代码:

let parent = container.resolve(ParentType.self)!
let child = container.resolve(ChildType.self)!
print(parent.getMyName())
print(child.getMyName())
print(parent.getMyChildName())
print(child.getMyParentName())

输出是这样的:

John
John Jr.
John Jr.
fatal error: unexpectedly found nil while unwrapping an Optional value

错误发生在这一行: return parent!.getMyName()

奇怪的是我在该行上放置了一个断点,这就是发生的事情:

  • 代码在断点处停止
  • 我看了一下self,它看起来正确初始化,parent属性看起来正确(对父实例的引用)
  • 我“跳过”,发生错误,现在parent属性是nil

我对这种循环依赖做错了吗?

此代码位于“空”单视图 iOS 应用程序中,仅通过 Carthage 添加了 Swinject 作为依赖项。

XCode 版本 7.2.1

通过 Carthage 安装的 Swinject 1.1 版

4

1 回答 1

1

问题是由于parent属性Child定义为weak属性而引起的。

让我们将实例命名如下。

let parentA = container.resolve(ParentType.self)!
let childB = container.resolve(ChildType.self)!

这里的父级childB是与 不同的实例parentA。由于isparent的属性,它被设置为在创建实例之后。childBweaknilchildB

另一方面,child属性 ofParent是一种strong属性。childof的实例与parentA不同childB,但该child实例由 持有parentA

如果您需要直接访问子实例,您可以添加var child: ChildType? { get }ParentType协议中。

关于循环依赖的概念,parentA' childsparentparentA,就是同一个例子。

如果ParentType注册如下,

container.register(ParentType.self) { r in
    Parent(child: r.resolve(ChildType.self)!)
}
.inObjectScope(.None)

parentA的和是不同child的实例。parentparentA

于 2016-03-10T13:25:59.163 回答