簡體   English   中英

如何使UITabBarController懶惰地加載視圖控制器?

[英]How to make UITabBarController load view controllers lazily?

我有一個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時?

我在我的一個應用程序中做了這件事。 訣竅是讓你的視圖控制器不是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

代碼肯定會變得更干,但你明白了。

你想偷懶加載什么?

這是一個非常標准的UITabBarController實現。 在我寫的一個應用程序中,我有一個非常類似的東西。 在我的代碼中,viewDidLoad(在控制器將其關聯的視圖加載到內存中之后調用的方法)在觸摸選項卡之前不會被調用。

我相信你編碼的方式(除了所有自動釋放的對象)是創​​建這種UI的首選方法。

UITabBarController要求為其viewControllers屬性設置實際的視圖控制器 - Apple的框架沒有延遲加載。 標簽欄控制器依賴於為其屬性加載的控制器的某些方面。 但是,在第一次按下選項卡之前,它不會調用viewDidLoad

你可以做的是創建你自己的“占位符”視圖控制器,在其viewDidLoadviewWillAppear方法中,它在標簽欄控制器中用它的實際視圖控制器替換它自己。 這樣,您可以最小化由標簽欄控制器保持的視圖控制器使用的內存,直到您加載某個選項卡的視圖控制器並將其替換為更多內存和處理器密集型控制器。

旁注:您需要直接更改選項卡欄控制器的viewControllers屬性,而不是使用setViewControllers:animated:方法,這樣您的用戶每次加載新控制器時都不會看到動畫。

您可以隨時使用UITabBarController並自行管理標簽欄,當有人選擇標簽時,您可以在didSelectIndex方法中按下viewcontrollers視圖

在自定義UITabBarController的didSelectItem方法中,您應該只是進行此調用:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM