Przełączasz się do widoku karty TabBar w sposób programowy?

159

Załóżmy, że mam UIButtonwidok jednej karty w mojej aplikacji na iPhone'a i chcę, aby otwierał inną kartę na pasku kart w TabBarController. Jak napisałem kod, aby to zrobić?

Zakładam, że wyładowuję istniejący widok i ładuję określony widok karty, ale nie jestem pewien, jak dokładnie napisać kod.

rottendevice
źródło
Mam problemy z powyższymi metodami, chłopaki pomagają w moim [pytaniu] [1] [1]: stackoverflow.com/questions/19742416/…
Roman Simenok

Odpowiedzi:

399

Wypróbuj ten kod w języku Swift lub Objective-C

Szybki

self.tabBarController.selectedIndex = 1

Cel C

[self.tabBarController setSelectedIndex:1];
Jordania
źródło
8
Zwróć uwagę, że jeśli indeks jest mapowany na kartę w kontrolerze widoku Więcej (jeśli masz więcej niż pięć kart), to nie zadziała. W takim przypadku użyj -setSelectedViewController:.
Joe D'Andrea
Po wykonaniu tej czynności i pomyślnej zmianie kart nie mogę już normalnie wybierać paska kart. AKTUALIZACJA: było to w jakiś sposób związane z wywołaniem popToRootViewController tuż przed programową zamianą kart.
Adam Johns
Ale jak nie zadziała Self, jeśli chcę zmienić kartę. powiedzmy, że kliknę kartę 3 i pokaż alert Wyświetl teraz, gdy użytkownik naciska ok, chcę ponownie przełączyć się na kartę 1. Self nie będzie miał racji, ponieważ nie jest to obecny obiekt. Dobrze?
Alix
Działa to dobrze, ale muszę też przekazywać dane podczas przełączania zakładek. Na karcie mam etykietę, na której się przełączam, musi zostać zaktualizowana, gdy tylko zmienię kartę.! Jakieś łatwe rozwiązanie tego problemu?
Md Rais,
@AdamJohns Jak udało Ci się rozwiązać problem. aby zachowywał się jak natywny tabBar. powinien wyskoczyć do rootViewController przy drugim kliknięciu.
Waqas
20

Zwróć uwagę, że zakładki są indeksowane począwszy od 0. Tak więc działa następujący fragment kodu

tabBarController = [[UITabBarController alloc] init];
.
.
.
tabBarController.selectedViewController = [tabBarController.viewControllers objectAtIndex:4];

przechodzi do piątej zakładki w pasku.

John Smith
źródło
12

Moim zdaniem selectedIndexlub używanie objectAtIndexniekoniecznie jest najlepszym sposobem na zmianę karty. Jeśli zmienisz kolejność kart, wybór indeksu zakodowanego na stałe może zepsuć poprzednie zachowanie aplikacji.

Jeśli masz odniesienie do obiektu kontrolera widoku, do którego chcesz się przełączyć, możesz wykonać:

tabBarController.selectedViewController = myViewController

Oczywiście musisz się upewnić, że myViewControllernaprawdę znajduje się na liście tabBarController.viewControllers.

Thomas T.
źródło
Musiałem wybrać moreNavController i to jedyny sposób, aby to zrobić, o ile wiem
Ossir
9

Możesz po prostu ustawić selectedIndexwłaściwość w UITabBarController na odpowiedni indeks, a widok zostanie zmieniony tak, jak użytkownik dotknął przycisku karty.

Alex Deem
źródło
6
Z jedną małą różnicą jest to, że metoda delegata, która może informować o przełączaniu kart użytkownika, nie jest wywoływana.
Brad The App Guy
3
Ustawienie selectedIndexrównież nie działa dla mnie z indeksami> 4, ale selectedViewControllerdziała.
bugloaf
3

Wypróbowałem to, co zasugerowało Disco S2, było blisko, ale tak się skończyło. Zostało to wywołane po wykonaniu czynności w innej karcie.

for (UINavigationController *controller in self.tabBarController.viewControllers)
{
    if ([controller isKindOfClass:[MyViewController class]])
    {
        [self.tabBarController setSelectedViewController:controller];
        break;
    }
}
Skakałem
źródło
2

W przypadkach, w których możesz przenosić karty, oto kod.

for ( UINavigationController *controller in self.tabBarController.viewControllers ) {
            if ( [[controller.childViewControllers objectAtIndex:0] isKindOfClass:[MyViewController class]]) {
                [self.tabBarController setSelectedViewController:controller];
                break;
            }
        }
StuStirling
źródło
2

Podobnie jak rozwiązanie Stuarta Clarka, ale dla Swift 3:

func setTab<T>(_ myClass: T.Type) {
    var i: Int = 0
    if let controllers = self.tabBarController?.viewControllers {
        for controller in controllers {
            if let nav = controller as? UINavigationController, nav.topViewController is T {
                break
            }
            i = i+1
        }
    }
    self.tabBarController?.selectedIndex = i
}

Użyj tego w ten sposób:

setTab(MyViewController.self)

Zwróć uwagę, że mój tabController łączy do viewControllers za navigationControllers. Bez navigationControllers wyglądałoby to tak:

if let controller is T {
Json
źródło
Bez pętli, bez kontrolerów nawigacji: func selectViewController <ViewControllerModel> (typ: ViewControllerModel.Type) {self.selectedViewController = self.viewControllers? .First (gdzie: {viewController in viewController to ViewControllerModel})}
dev_exo,
1

Chciałem móc określić, która karta jest wyświetlana według klasy, a nie indeksu, ponieważ uważałem, że jest to solidne rozwiązanie, które jest mniej zależne od sposobu okablowania IB. Nie znalazłem rozwiązania Disco ani Jopeda do działania, więc stworzyłem tę metodę:

-(void)setTab:(Class)class{
    int i = 0;
    for (UINavigationController *controller in self.tabBarContontroller.viewControllers){
        if ([controller isKindOfClass:class]){
            break;
        }
        i++;
    }
    self.tabBarContontroller.selectedIndex = i;
}

nazywasz to tak:

[self setTab:[YourClass class]];

Mam nadzieję, że to komuś pomoże

Stuart Clark
źródło
To działało świetnie! Przepisałem go dla Swift3 w innej odpowiedzi.
Json
1

Mój problem jest trochę inny, muszę przełączyć się z jednego childViewController w 1. tabBar na home viewController 2. tabBar. Po prostu korzystam z rozwiązania znajdującego się na piętrze:

tabBarController.selectedIndex = 2

Jednak po przełączeniu na stronę główną drugiego tabBar zawartość jest niewidoczna. A kiedy debuguję, viewDidAppear, viewWillAppear, viewDidLoad, żaden z nich nie jest wywoływany. Moje rozwiązanie polega na dodaniu następującego kodu w UITabBarController:

override var shouldAutomaticallyForwardAppearanceMethods: Bool 
{
    return true
}
Jin
źródło
0

Użyj w AppDelegate.mpliku:

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

     NSLog(@"Selected index: %d", tabBarController.selectedIndex);

    if (viewController == tabBarController.moreNavigationController)
    {
        tabBarController.moreNavigationController.delegate = self;
    }

    NSUInteger selectedIndex = tabBarController.selectedIndex;

    switch (selectedIndex) {

        case 0:
            NSLog(@"click me %u",self.tabBarController.selectedIndex);
            break;
        case 1:
            NSLog(@"click me again!! %u",self.tabBarController.selectedIndex);
            break;

        default:
            break;

    }

}
Rakesh Singh
źródło
0

Podobnie jak rozwiązanie Stuarta Clarka, ale dla Swift 3 i używając identyfikatora przywracania, aby znaleźć właściwą kartę:

private func setTabById(id: String) {
  var i: Int = 0
  if let controllers = self.tabBarController?.viewControllers {
    for controller in controllers {
      if let nav = controller as? UINavigationController, nav.topViewController?.restorationIdentifier == id {
        break
      }
      i = i+1
    }
  }
  self.tabBarController?.selectedIndex = i
}

Użyj go w ten sposób („Ludzie” i „Roboty” muszą być również ustawione w scenorysie dla określonego kontrolera widoku i jego identyfikatora przywrócenia lub użyj identyfikatora scenorysu i zaznacz „użyj identyfikatora scenorysu” jako identyfikatora przywrócenia):

struct Tabs {
    static let Humans = "Humans"
    static let Robots = "Robots"
}
setTabById(id: Tabs.Robots)

Zwróć uwagę, że mój tabController łączy do viewControllers za navigationControllers. Bez navigationControllers wyglądałoby to tak:

if controller.restorationIdentifier == id {
Json
źródło
0
import UIKit

class TabbarViewController: UITabBarController,UITabBarControllerDelegate {

//MARK:- View Life Cycle

override func viewDidLoad() {
    super.viewDidLoad()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

//Tabbar delegate method
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    let yourView = self.viewControllers![self.selectedIndex] as! UINavigationController
    yourView.popToRootViewController(animated:false)
}



}
Davender Verma
źródło
1
Zwykle lepiej jest wyjaśnić rozwiązanie, zamiast publikować kilka wierszy anonimowego kodu. Możesz przeczytać Jak napisać dobrą odpowiedź , a także wyjaśnić odpowiedzi w całości oparte na kodzie
Anh Pham