2013-11-09 3 views
0

Я создал пользовательский UITabBarController со Storiesboards/Segues и UIViewController. Вот ссылка на него: https://github.com/mhaddl/MHCustomTabBarControllerDealloc вызывается на UIViewControllers, которые хранятся в NSMutableDictionary и представлены UIViewControllerContainment

UIViewControllers, которые будут представлены контейнером, хранятся в NSMutableDictionary (ключи являются идентификаторами segues). Все работает нормально до тех пор, пока не будет достигнута точка, когда я вернусь к ранее представленному ViewController. На данный момент «dealloc» вызывается на этом ViewController перед его представлением.

Как я могу предотвратить вызов «dealloc», чтобы его можно было использовать для отмены подписки на уведомления и делегатов nil.

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 
+0

Вы используете ARC? –

ответ

3

"На данный момент "dealloc" вызывается на этом ViewController до представления." -- нет, не совсем. Dealloc вызывается на контроллере, который никогда не попадает на экран, а не тот, с которого вы пришли изначально или возвращаетесь обратно. Способ настройки segue и тот факт, что вы держите ссылку на свои контроллеры в словаре, означает, что они никогда не освобождаются. Segues (кроме разматывания) ВСЕГДА создавайте новые контроллеры представлений, поэтому происходит то, что новый экземпляр, например VC1, создается при нажатии на первую вкладку (и срабатывает segue), но вы никогда ничего не делаете с этим контроллером (который будет self.destinationViewController в пользовательском классе segue), поэтому он освобождается, как только выйдет метод выполнения.

В зависимости от того, где вы настроили каких-либо делегатов или наблюдателей уведомлений, это может быть не проблема - этот контроллер, который был создан, а затем немедленно освобожден, никогда не имеет метода viewDidLoad, поэтому, если вы делаете эти вещи в viewDidLoad, они выиграли никогда не бывает для этого контроллера переходного режима.

Если вы не хотите, чтобы это произошло, вам нужно сделать свои переходы в коде без использования segues.

+0

Ах, большое спасибо за понимание! Отмечен ответ как решение. – mhaddl