如何使UITabBarController懒惰地加载视图控制器?

时间:2009-07-28 22:33:14

标签: iphone

我有一个UITabBarController创建的programaticaly管理UIViewController的4个子类。类似的东西:

//Create Controller 1
    self.terminal = [[[TerminalController alloc] initWithNibName:@"TerminalView" bundle:nil] autorelease];
    UINavigationController* navTerminal = [[[UINavigationController alloc] initWithRootViewController:terminal] autorelease];
    navTerminal.title = __(@"Terminal");
    navTerminal.navigationBar.barStyle = UIBarStyleBlackOpaque;
    navTerminal.tabBarItem.image = [UIImage imageNamed:@"tab_terminal.png"];        

    //Create Controller 2
    self.history = [[[HistoryController alloc] initWithNibName:@"HistoryView" bundle:nil] autorelease];
    UINavigationController* navHistory =  [[[UINavigationController alloc] initWithRootViewController:history] autorelease];
    navHistory.title = __(@"History");
    navHistory.navigationBar.barStyle = UIBarStyleBlackOpaque;
    navHistory.tabBarItem.image = [UIImage imageNamed:@"tab_history.png"];

    //Create Controller 3
    self.settings = [[[SettingsController alloc] initWithNibName:@"SettingsView" bundle:nil] autorelease];
    UINavigationController* navSettings =  [[[UINavigationController alloc] initWithRootViewController:settings] autorelease];
    navSettings.title = __(@"Settings");
    navSettings.navigationBar.barStyle = UIBarStyleBlackOpaque;
    navSettings.tabBarItem.image = [UIImage imageNamed:@"tab_settings.png"];

    //Create Controller 4
    HelpController* help = [[[HelpController alloc] initWithNibName:@"HelpView" bundle:nil] autorelease];
    UINavigationController* navHelp =  [[[UINavigationController alloc] initWithRootViewController:help] autorelease];
    navHelp.title = __(@"Help");
    navHelp.navigationBar.barStyle = UIBarStyleBlackOpaque;
    navHelp.tabBarItem.image = [UIImage imageNamed:@"tab_help.png"];

    //Create Tab Bar an add it's view to window.
    self.tabBar = [[[UITabBarController alloc] initWithNibName:nil bundle:nil] autorelease];
    tabBar.viewControllers = [[[NSArray alloc] initWithObjects:navTerminal, navHistory, navSettings, navHelp, nil] autorelease];
    tabBar.delegate = self;     

    [window addSubview:tabBar.view];

有没有办法告诉UITabBarController懒惰地加载视图控制器? ej,当用户点击其中一个标签栏项目或者调用tabBarController setSelectedIndex时?

5 个答案:

答案 0 :(得分:12)

我正在我的一个应用程序中执行此操作。诀窍是让你的视图控制器不是UITabBarController的子类,而是UIViewController,并实现UITabBarDelegate。我在IB中为此创建了视图,布置了标签栏(带有正确的按钮,图像,标签等)和占位符UIView,用于正确放置交换的子视图。视图切换发生在tabBar:didSelectItem:它看起来像这样:

// MyTabBarController.h
@class MyFirstViewController;
@class MySecondViewController;
@class MyThirdViewController;

@interface MyTabBarController : UIViewController <UITabBarDelegate> {
    IBOutlet UIView *placeholderView;
    IBOutlet UITabBar *tabBar;
    MyFirstViewController *firstViewController;
    MySecondViewController *secondViewController;
    MyThirdViewController *thirdViewController;
    UIViewController *currentViewController;
}
@property (nonatomic, retain) MyFirstViewController *firstViewController;
@property (nonatomic, retain) MySecondViewController *secondViewController;
@property (nonatomic, retain) MyThirdViewController *thirdViewController;

- (void) switchToView:(UIViewController*)aViewController;
@end


//  MyTabBarController.m
#import "MyTabBarController.h"
#import "MyFirstViewController.h"
#import "MySecondViewController.h"
#import "MyThirdViewController.h"

enum {
    kView_First = 1,
    kView_Second,
    kView_Third
};

@implementation MyTabBarController

@synthesize firstViewController, secondViewController, thirdViewController;

- (void) viewDidLoad {
    // Default to first view.
    tabBar.selectedItem = [tabBar.items objectAtIndex:0];
    MyFirstViewController *viewController = [[MyFirstViewController alloc] initWithNibName:@"FirstView" bundle:nil];
    self.firstViewController = viewController;
    [viewController release];
    [self switchToView:firstViewController];
}

- (void)viewWillAppear:(BOOL)animated {
    // Tell our subview.
    if( currentViewController != nil ) {
        [currentViewController viewWillAppear:animated];
    }
}

- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
    switch (item.tag) {
        case kView_First: {
            if (firstViewController == nil) {
                MyFirstViewController *viewController = [[MyFirstViewController alloc]
                    initWithNibName:@"FirstView" bundle:nil];
                self.firstViewController = viewController;
                [viewController release];
            }

            [self switchToView:firstViewController];
        }
        break;

        case kView_Second:
            if (secondViewController == nil) {
                MySecondViewController *viewController = [[MySecondViewController alloc]
                initWithNibName:@"SecondView" bundle:nil];
                self.secondViewController = viewController;
                [viewController release];
            }

            [self switchToView:secondViewController];
            break;

        case kView_Third: {
            if (timesViewController == nil) {
                MyThirdViewController *viewController = [[MyThirdViewController alloc]
                initWithNibName:@"ThirdView" bundle:nil];
                self.thirdViewController = viewController;
                [viewController release];
            }

            [self switchToView:thirdViewController];
        }
        break;              
    }
}

- (void) switchToView:(UIViewController*)aViewController {
    if( aViewController == currentViewController ) return;

    UIView *aView= aViewController.view;                
    [aViewController viewWillAppear:NO];
    if( currentViewController != nil ) {
        [currentViewController viewWillDisappear:NO];
        [currentViewController.view removeFromSuperview];       
    }
    aView.frame = placeholderView.frame;
    [self.view insertSubview:aView aboveSubview:placeholderView];
    if( currentViewController != nil ) {
        [currentViewController viewDidDisappear:NO];
    }
    [aViewController viewDidAppear:NO];
    currentViewController = aViewController;
}
@end

代码肯定会变得更干,但你明白了。

答案 1 :(得分:5)

你想懒得加载什么?

这是一个非常标准的UITabBarController实现。在我写的一个应用程序中,我有一个非常类似的东西。在我的代码中,viewDidLoad(在控制器将其关联的视图加载到内存中之后调用的方法)在触摸选项卡之前不会被调用。

我确实相信你编码的方式(除了所有自动释放的对象)是创​​建这种UI的首选方法。

答案 2 :(得分:2)

UITabBarController要求为其viewControllers属性设置实际的视图控制器 - Apple的框架没有延迟加载。标签栏控制器依赖于为其属性加载的控制器的某些方面。但是,在第一次按下选项卡之前,它不会调用viewDidLoad

您可以做的是创建自己的“占位符”视图控制器,在其viewDidLoadviewWillAppear方法中,使用其实际视图控制器替换标签栏控制器中的自身。这样,您可以最小化由标签栏控制器保持的视图控制器使用的内存,直到您加载某个选项卡的视图控制器并将其替换为更多的内存和处理器密集型控制器。

附注:您需要直接更改标签栏控件的viewControllers属性,而不是使用setViewControllers:animated:方法,这样您的用户每次加载时都不会看到动画新控制器。

答案 3 :(得分:0)

当有人选择一个标签时,你总是不能使用UITabBarController并管理标签栏你在didSelectIndex方法中按下viewcontrollers视图

答案 4 :(得分:0)

在自定义UITabBarController的didSelectItem方法中,您只需进行此调用:

[self setSelectedViewController :[self.viewControllers objectAtIndex:0]];