I have seen that the scope TyphoonScopeObjectGraph is useful for having circular dependencies, such a a controller and view, that has a delegate property pointing back to the controller.
So I tested this with the following scenario:
Controller A pushes Controller B which pushes Controller C that has a weak delegate pointing back to Controller A.
Controller C has a button that executes a method on this delegate.
I have seen that Typhoon instantiates Controller C, it properly sets Controller A as delegate, however when the button is pressed the delegate has been updated to nil.
This is the assembly code:
- (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]];
}];
}
This is ViewControllerC:
@interface ViewControllerC : UIViewController
@property (weak, nonatomic) id<ViewControllerDelegate> delegate;
@end
@implementation ViewControllerC
- (IBAction)buttonAction:(id)sender {
[self.delegate viewControllerDidTapButton:self];
}
@end
This is ViewControllerA:
@interface ViewControllerA ()<ViewControllerDelegate>
@end
@implementation ViewControllerA
- (void)viewDidLoad {
[super viewDidLoad];
self.title = self.name;
}
- (void)viewControllerDidTapButton:(UIViewController *)viewController {
[self.navigationController popToRootViewControllerAnimated:YES];
}
Why is this? Is there a workaround?
The TyphoonScopeObjectGraph creates a shared scope only during a call to assemble a particular definition. So if:
If you want to create a circular dependency back to something that was built earlier you need either TyphoonScopeSingleton
or TyphoonScopeWeakSingleton
. The latter sounds appropriate in this case - for our own projects we sometimes use that scope for a shared 'context' object that should be discarded when no more references point to it.