推送视图控制器时的循环依赖
Circular dependency when pushing view controllers
我已经看到范围 TyphoonScopeObjectGraph 对于循环依赖很有用,例如控制器和视图,它有一个委托 属性 指向控制器。
所以我在以下场景中对此进行了测试:
控制器 A 推送控制器 B,控制器 B 推送控制器 C,后者具有指向控制器 A 的弱委托。
控制器 C 有一个按钮,用于在此委托上执行方法。
我看到 Typhoon 实例化了 Controller C,它正确地将 Controller A 设置为委托,但是当按下按钮时,委托已更新为 nil。
这是汇编代码:
- (ViewControllerA *)viewControllerA {
return [TyphoonDefinition withClass:[ViewControllerA class]
configuration:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(name) with:@"Hello world!"];
}];
}
- (ViewControllerC *)viewControllerC {
return [TyphoonDefinition withClass:[ViewControllerC class]
configuration:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(delegate) with:[self viewControllerA]];
}];
}
这是 ViewControllerC:
@interface ViewControllerC : UIViewController
@property (weak, nonatomic) id<ViewControllerDelegate> delegate;
@end
@implementation ViewControllerC
- (IBAction)buttonAction:(id)sender {
[self.delegate viewControllerDidTapButton:self];
}
@end
这是 ViewControllerA:
@interface ViewControllerA ()<ViewControllerDelegate>
@end
@implementation ViewControllerA
- (void)viewDidLoad {
[super viewDidLoad];
self.title = self.name;
}
- (void)viewControllerDidTapButton:(UIViewController *)viewController {
[self.navigationController popToRootViewControllerAnimated:YES];
}
这是为什么?有解决方法吗?
TyphoonScopeObjectGraph 仅在调用 assemble 特定定义期间创建共享范围 。所以如果:
- View Controller A 是在一次调用中构建的。
- 然后构建 View Controller C,创建对 View Controller A 的依赖将创建一个新实例,由于弱引用,该实例随后将再次变为 nil。
如果你想创建一个循环依赖回到之前构建的东西,你需要 TyphoonScopeSingleton
或 TyphoonScopeWeakSingleton
。后者在这种情况下听起来很合适——对于我们自己的项目,我们有时会将该范围用于共享 'context' 对象,当没有更多引用指向它时应该丢弃该对象。
我已经看到范围 TyphoonScopeObjectGraph 对于循环依赖很有用,例如控制器和视图,它有一个委托 属性 指向控制器。
所以我在以下场景中对此进行了测试:
控制器 A 推送控制器 B,控制器 B 推送控制器 C,后者具有指向控制器 A 的弱委托。
控制器 C 有一个按钮,用于在此委托上执行方法。
我看到 Typhoon 实例化了 Controller C,它正确地将 Controller A 设置为委托,但是当按下按钮时,委托已更新为 nil。
这是汇编代码:
- (ViewControllerA *)viewControllerA {
return [TyphoonDefinition withClass:[ViewControllerA class]
configuration:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(name) with:@"Hello world!"];
}];
}
- (ViewControllerC *)viewControllerC {
return [TyphoonDefinition withClass:[ViewControllerC class]
configuration:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(delegate) with:[self viewControllerA]];
}];
}
这是 ViewControllerC:
@interface ViewControllerC : UIViewController
@property (weak, nonatomic) id<ViewControllerDelegate> delegate;
@end
@implementation ViewControllerC
- (IBAction)buttonAction:(id)sender {
[self.delegate viewControllerDidTapButton:self];
}
@end
这是 ViewControllerA:
@interface ViewControllerA ()<ViewControllerDelegate>
@end
@implementation ViewControllerA
- (void)viewDidLoad {
[super viewDidLoad];
self.title = self.name;
}
- (void)viewControllerDidTapButton:(UIViewController *)viewController {
[self.navigationController popToRootViewControllerAnimated:YES];
}
这是为什么?有解决方法吗?
TyphoonScopeObjectGraph 仅在调用 assemble 特定定义期间创建共享范围 。所以如果:
- View Controller A 是在一次调用中构建的。
- 然后构建 View Controller C,创建对 View Controller A 的依赖将创建一个新实例,由于弱引用,该实例随后将再次变为 nil。
如果你想创建一个循环依赖回到之前构建的东西,你需要 TyphoonScopeSingleton
或 TyphoonScopeWeakSingleton
。后者在这种情况下听起来很合适——对于我们自己的项目,我们有时会将该范围用于共享 'context' 对象,当没有更多引用指向它时应该丢弃该对象。