При программном создании UINavigationController и UITabBarController, как мне обращаться к их функциям (например, viewWillAppear?)

Я создаю свои Nav и TabBar в коде при запуске через: IN: myAppDelegate.m

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    // set up a local nav controller which we will reuse for each view controller
    UINavigationController *localNavigationController;

    // create tab bar controller and array to hold the view controllers
    tabBarController = [[UITabBarController alloc] init];
    NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:4];

    // setup the first view controller (Root view controller)
    RootViewController *myViewController;
    myViewController = [[RootViewController alloc] initWithTabBar];

    // create the nav controller and add the root view controller as its first view
    localNavigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];

    // add the new nav controller (with the root view controller inside it)
    // to the array of controllers
    [localControllersArray addObject:localNavigationController];

    // release since we are done with this for now
    [localNavigationController release];
    [myViewController release];

    // setup the first view controller just like the first 
    ResortsListViewController *resortsListViewController;
    resortsListViewController = [[ResortsListViewController alloc] initWithNibName:@"ResortsListView" bundle:nil];
    resortsListViewController.title = @"Category1";
    resortsListViewController.tabBarItem.image = [UIImage imageNamed:@"image1.png"];
    resortsListViewController.navigationItem.title=@"Category1";
    localNavigationController = [[UINavigationController alloc] initWithRootViewController:resortsListViewController];
    [localControllersArray addObject:localNavigationController]; 
    [localNavigationController release];

    // setup the second view controller just like the first 
    ResortsListViewController *resortsListViewController;
    resortsListViewController = [[ResortsListViewController alloc] initWithNibName:@"ResortsListView" bundle:nil];
    resortsListViewController.title = @"Category2";
    resortsListViewController.tabBarItem.image = [UIImage imageNamed:@"image2.png"];
    resortsListViewController.navigationItem.title=@"Category2";
    localNavigationController = [[UINavigationController alloc] initWithRootViewController:resortsListViewController];
    [localControllersArray addObject:localNavigationController]; 
    [localNavigationController release];

    // setup the third view controller just like the first 
    ResortsListViewController *resortsListViewController;
    resortsListViewController = [[ResortsListViewController alloc] initWithNibName:@"ResortsListView" bundle:nil];
    resortsListViewController.title = @"Category3";
    resortsListViewController.tabBarItem.image = [UIImage imageNamed:@"image3.png"];
    resortsListViewController.navigationItem.title=@"Category3";
    localNavigationController = [[UINavigationController alloc] initWithRootViewController:resortsListViewController];
    [localControllersArray addObject:localNavigationController]; 
    [localNavigationController release];

    [resortsListViewController release];

    // load up our tab bar controller with the view controllers
    tabBarController.viewControllers = localControllersArray;

    // release the array because the tab bar controller now has it
    [localControllersArray release];

    // add the tabBarController as a subview in the window
    [window addSubview:tabBarController.view];

    // need this last line to display the window (and tab bar controller)
    [window makeKeyAndVisible];


}

Как видите, я повторно использую ResortsListViewController для отображения различных категорий (курорты с пляжами, курорты с бассейнами, курорты с эспрессо-барами)... теперь, не беспокоя меня (усмехается) глупостью моих категорий (потому что это тестовое приложение) мне нужно сделать несколько вещей:

  1. Мне нужно знать, какая вкладка вызвала отображение ResortsListViewController. Я надеялся использовать TAG, но «initWithRootViewController» не имеет элемента управления «tag». Итак, если я использую имя файла изображения, которое является именем категории, я могу использовать это имя файла, чтобы различать категории... или даже имя элемента навигации. Мне нужно знать, есть ли у ResortsListViewController способ узнать, какой элемент панели вкладок вызвал его отображение. Я думал найти «действие», которое я мог бы назначить элементу панели вкладок, но это не так, как работает tabbarcontroller.

  2. При переходе с одной вкладки на другую представление действительно меняется, меняется заголовок ResortsListViewController и т. д., но содержащееся в нем TABLEVIEW не очищается и не отображает никаких новых данных. Поискав в Интернете, я нашел возможное решение:

http://discussions.apple.com/thread.jspa?threadID=1529769&tstart= 0

в основном говоря:

Чтобы UINavigationControllers мог отправлять сообщения «viewWill/Did/Appear/Disappear», он должен получить «viewWill/Did/Appear/Disappear» из своего контейнера.

Каков контейнер для моих UINavigationControllers в этой ситуации? myAppDelegate определен в файле .h как:

NSObject <UIApplicationDelegate, CLLocationManagerDelegate>

и не имеет:

- (void)viewWillAppear:(BOOL)animated {
}

раздел. Когда я добавляю один, он говорит: «NSObject может не отвечать на -viewWillAppear» в отладчике.

Любая помощь там?


person Jann    schedule 07.02.2010    source источник


Ответы (3)


1) Это довольно просто. Вам необходимо установить свойство delegate для UITabBarController. Вы должны установить это на объект контроллера, которому принадлежит ваш tabbarcontroller (или ваш делегат приложения, если это ваша настройка). Какой бы объект ни был установлен в качестве делегата, он получит:

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController

И

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController

для управления выбором вкладок. Поместите один из этих методов в реализацию любого объекта, который вы задали в качестве делегата (вы бы хотели, чтобы это был объект, которому принадлежат все контроллеры).

2) Если у вас есть UIViewController, который отображается как выбор вкладки (например, ResortsListViewController), вам нужно будет самостоятельно поместить метод viewWillAppear в реализацию контроллера:

@implementation ResortsListViewController

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle {
...
}

... etc. ....

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[table reloadData];
}

...

@end

Дайте мне знать, если я неправильно понял вторую часть вашего вопроса.

person Matthew McGoogan    schedule 07.02.2010
comment
Я попробую это. Сообщим в утренние часы (воскресенье). Вторая часть немного сбивает с толку, потому что я могу добавить viewWillAppear XCode не будет автоматически заполнять это и предупреждает, что myAppDelegate может не отвечать на -viewWillAppear. Понимать? - person Jann; 07.02.2010
comment
Ваш appDelegate не должен отвечать на viewWillAppear, если это NSObject (как в любом стандартном шаблоне Xcode). Вы упомянули: ResortsListViewController *resortsListViewController. Файл, в котором это реализовано, — это место, где вы хотите поместить свой метод viewWillAppear. - person Matthew McGoogan; 07.02.2010

Хорошо, вот так: это это правильный ответ на вопрос, однако он оказался не таким сложным. Все, что мне нужно было сделать, это следующее:

Создайте свойство в ResortViewController типа int с именем переменной whichChoice (например). Затем обратитесь к нему в настройках TabBarController а-ля:

// setup the first view controller just like the first 
    ResortsListViewController *resortsListViewController;
    resortsListViewController = [[ResortsListViewController alloc]     initWithNibName:@"ResortsListView" bundle:nil];
    //  START HERE IS THE CHANGE
    resortsListViewController.whichChoice = 1;
    //  END HERE IS THE CHANGE
    resortsListViewController.title = @"Category1";
    resortsListViewController.tabBarItem.image = [UIImage imageNamed:@"image1.png"];
    resortsListViewController.navigationItem.title=@"Category1";
    localNavigationController = [[UINavigationController alloc] initWithRootViewController:resortsListViewController];
    [localControllersArray addObject:localNavigationController]; 
    [localNavigationController release];

Чтобы узнать, какая вкладка была нажата, когда мой ResortsListViewController вступает во владение, я просто запрашиваю переменную класса: whichChoice, чтобы получить ответ.

Такие вещи настолько просты, что вы пропускаете их. Я думал, что вам нужно передать переменную в действие и указать, куда она пойдет с целью, как вы это делаете в других объектах, но когда вы настраиваете все заранее время вам не нужно делать это. Теперь, сказав это, динамически установить "whatChoice" не так просто, не задумываясь... но установить его в ИЗВЕСТНУЮ переменную при настройке - это нормально.

Для ответа № 2 я просто поместил переменный стиль IBOutlet в свой класс, подключил его к таблице, а затем последовал вашим инструкциям, потому что без переменной в IBOutlet и ее подключения к таблице нет ссылки на вид таблицы. По какой-то причине подключение таблицы просто к VIEW "Referenceing Outlet" и вызов [self.tableview reloadData] не помогли.

Но по большей части ваши ответы были правильными и вели меня в правильном направлении. Кроме того, я действительно ненавижу то, что вам нужно щелкнуть правой кнопкой мыши и перетащить отсюда сюда в IB, если у вас есть созданный вами элемент IB. Вы должны иметь возможность подключить его в коде, используя его ObjectId (или что-то в этом роде). Это было бы больше в соответствии с программистами. Я знаю, что IB создан для того, чтобы программировать было проще для дизайнеров, но о боже, виликеры... мне сложно это понять! Я заканчиваю тем, что бросаю IB и создаю элементы в коде большую часть времени... что я не знаю, так же быстро выполняется. Я склонен думать, что нет... но у меня нет доказательств обратного.

person Jann    schedule 08.02.2010

Посетите страницу Как добавить UINavigationController программно

Пожалуйста, перейдите по ссылке выше и получите всю информацию о UINavigationController.

person niceamitsingh    schedule 06.12.2011
comment
Это бесполезно. Чтобы создать приведенный выше пример, я действительно прочитал документы. Они не полностью объясняют, что я спрашивал. - person Jann; 06.12.2011
comment
Я попытался объяснить только основы. Подскажите пожалуйста, что смотрите? Я должен помочь тебе. - person niceamitsingh; 31.01.2012