我已经构建了一个自定义的 UITabBarController,其中包含 Storyboards/Segues 和 UIViewController。这是它的链接:https://github.com/mhaddl/MHCustomTabBarController
将由容器呈现的 UIViewControllers 存储在 NSMutableDictionary 中(键是 segues 的标识符)。一切正常,直到我回到之前呈现的 ViewController 为止。此时“dealloc”在这个 ViewController 被呈现之前被调用。
如何防止调用“dealloc”以便它可以用于取消订阅通知和 nil 委托(delegate)。
MHCustomTabBarController:
@implementation MHCustomTabBarController {
NSMutableDictionary *_viewControllersByIdentifier;
}
- (void)viewDidLoad {
[super viewDidLoad];
_viewControllersByIdentifier = [NSMutableDictionary dictionary];
}
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.childViewControllers.count < 1) {
[self performSegueWithIdentifier:@"viewController1" sender:[self.buttons objectAtIndex:0]];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.destinationViewController.view.frame = self.container.bounds;
}
#pragma mark - Segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (![segue isKindOfClass:[MHTabBarSegue class]]) {
[super prepareForSegue:segue sender:sender];
return;
}
self.oldViewController = self.destinationViewController;
//if view controller isn't already contained in the viewControllers-Dictionary
if (![_viewControllersByIdentifier objectForKey:segue.identifier]) {
[_viewControllersByIdentifier setObject:segue.destinationViewController forKey:segue.identifier];
}
for (UIButton *aButton in self.buttons) {
[aButton setSelected:NO];
}
UIButton *button = (UIButton *)sender;
[button setSelected:YES];
self.destinationIdentifier = segue.identifier;
self.destinationViewController = [_viewControllersByIdentifier objectForKey:self.destinationIdentifier];
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if ([self.destinationIdentifier isEqual:identifier]) {
//Dont perform segue, if visible ViewController is already the destination ViewController
return NO;
}
return YES;
}
#pragma mark - Memory Warning
- (void)didReceiveMemoryWarning {
[[_viewControllersByIdentifier allKeys] enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
if (![self.destinationIdentifier isEqualToString:key]) {
[_viewControllersByIdentifier removeObjectForKey:key];
}
}];
}
@end
MHTabBarSegue:
@implementation MHTabBarSegue
- (void) perform {
MHCustomTabBarController *tabBarViewController = (MHCustomTabBarController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) tabBarViewController.destinationViewController;
//remove old viewController
if (tabBarViewController.oldViewController) {
[tabBarViewController.oldViewController willMoveToParentViewController:nil];
[tabBarViewController.oldViewController.view removeFromSuperview];
[tabBarViewController.oldViewController removeFromParentViewController];
}
destinationViewController.view.frame = tabBarViewController.container.bounds;
[tabBarViewController addChildViewController:destinationViewController];
[tabBarViewController.container addSubview:destinationViewController.view];
[destinationViewController didMoveToParentViewController:tabBarViewController];
}
@end
最佳答案
“此时“dealloc”在这个 ViewController 被呈现之前被调用。” ——不,不是真的。 Dealloc 在一个永远不会出现在屏幕上的 Controller 上被调用,而不是你最初来自或要返回的 Controller 。你的 segue 设置方式,以及你在字典中保留对你的 Controller 的引用的事实,意味着它们永远不会被释放。 Segues(除了展开)总是实例化新的 View Controller ,所以发生的事情是当您单击第一个选项卡(并触发 segue)时创建一个新实例,例如 VC1,但您永远不会对该 Controller 执行任何操作(这将是自定义 segue 类中的 self.destinationViewController),因此一旦 perform 方法退出,它就会被释放。
根据您设置任何委托(delegate)或通知观察者的位置,这可能不是问题——这个创建并立即释放的 Controller 永远不会调用其 viewDidLoad 方法,因此如果您在 viewDidLoad 中执行这些操作,它们将不会这个 transient View Controller 永远不会发生。
如果您不希望这种情况发生,那么您需要在不使用转场的情况下在代码中进行转换。
关于ios - 在存储在 NSMutableDictionary 中并由 UIViewControllerContainment 呈现的 UIViewController 上调用 Dealloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19881692/