3 Stimmen

Wie verbinde ich zwei verschiedene Tab-Leistensymbole mit demselben Ansichtscontroller mit Storyboard?

Ich habe einen Tab-Bar-Controller in einer iPad-App mit 6 Elementen. Zwei der Symbole werden, wenn Sie darauf tippen, zu demselben Ansichtscontroller führen. Dieser Ansichtscontroller hat eine Liste von Elementen, die er anzeigen wird, die sich je nachdem, auf welches der Tab-Bar-Symbole Sie getippt haben, leicht ändern werden.

Wie richte ich das mit Storyboards ein? Es ist möglich, die Beziehung zweimal zum selben Ansichtscontroller zu ziehen, aber dann werden einfach zwei identische Symbole in der Tab-Leiste angezeigt. Ich möchte, dass die beiden Auswahlmöglichkeiten unterschiedliche Symbole und Namen haben.

0voto

brian Punkte 41

Ich konnte dies erreichen, indem ich die Tab-Titel in viewDidLoad gesetzt habe. Ich habe 2 Beziehungen zum selben Ansichtscontroller erstellt. Dann habe ich den Bar-Element-Titel auf "Not Set" gesetzt. Schließlich habe ich die viewDidLoad-Methode wie folgt festgelegt:

  UITabBarController *tc = (UITabBarController *)self.parentViewController;
  NSArray *vcs = tc.viewControllers;
  BOOL tabsInitialized=YES;
  for (UIViewController *vc in vcs)
  {
    if ([vc.tabBarItem.title isEqualToString:@"Not Set"])
    {
      tabsInitialized = NO;
      break;
    }
  }
  if (!tabsInitialized)
  {
    int I=1;
    for (UIViewController *vc in vcs)
    {
      vc.tabBarItem.title = [NSString stringWithFormat:@"Tab %i", i++];
    }
  }
}

0voto

Bill Feth Punkte 313

Ich weiß, dass diese Frage vor einiger Zeit beantwortet wurde, aber keiner der Lösungen erwähnte die direkte Verwendung einer UITabBar und das Überschreiben ihrer UITabBarDelegate tabBar(_, didSelect item:) Methode, anstatt einen UITabBarController die Auswahl indirekt handhaben zu lassen.

extension MyListViewController: UITabBarDelegate {

    func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {

        // Setze einen Filter basierend auf dem ausgewählten Element oder seinem Tag (Tag-Werte können in IB zugewiesen werden)
        switch item.tag {
            // Wende den Filter auf deine Datenquelle basierend auf dem item.tag an
        }

        // Oder wenn du einen CoreData NSFetchedResultsController verwendest, setze seine Prädikate:
        // resultsController.predicate = makePredicate(item.tag)
        // resultsController.performFetch()

        tableView.reloadData()
    }
}

Indem du UITabBarDelegate Methoden direkt überschreibst, hast du direkte Kontrolle über das Auswahlverhalten des Tabs. So könntest du dieselbe Instanz deines UIViewController wiederverwenden, anstatt dass der UITabBarController ständig eine neue Instanz des UIViewController für jeden Tab erstellt. Zum Beispiel könntest du in der didSelect Methode einen Filter auf eine bestehende Liste von Elementen in einem UITableView anwenden, anstatt eine neue Instanz der Liste in einem neuen UITableView zu erstellen, wie es die anderen Lösungen tun.

Hinweis: Wenn du einen UITabBar in deinem View Controller im Code oder in IB verwendest, erkennt UIKit dessen Existenz nicht und "unterlappende" Scrollansichten (z.B. UITableView, UICollectionView) passen ihre contentInset nicht automatisch an. Auch wird das Verankern des unteren Teils des UITabBar nicht korrekt auf einem Gerät mit nicht-nullen sicheren Bereichsrändern funktionieren, wenn du es an den unteren Bereich des sicheren Bereichs ankerst (es wird mit einer Lücke zwischen sich und dem Bildschirmrand "schweben").

Lösung (Teil 1): Setze die oberste Beschränkung speziell auf die UITabBar-Instanz: Verankere zuerst den unteren Rand der Tab-Leiste am Superview und den oberen Rand am unteren Rand des Sicheren Bereichs und setze die Konstante auf 49 (die Standardhöhe eines UITabBars zum Zeitpunkt dieses Schreibens). Dann wird es auf Geräten mit und ohne sicheren Bereich richtig aussehen.

Lösung (Teil 2): Du musst tableView.contentInset / collectionView.contentInset manuell anpassen, um sicherzustellen, dass der Inhalt unter der Tab-Leiste gescrollt werden kann. Du musst sicherstellen, dass das unterste Element immer noch über die untere Tab-Leiste gescrollt werden kann:

  1. Deaktiviere die automatische Anpassung des Inhaltsinsets in deinem viewDidLoad():

    tableView.contentInsetAdjustmentBehavior = .never
  2. Passe das UIScrollView.contentInset an einer passenden Stelle an, füge die folgende Methode hinzu und rufe sie entweder in viewDidLoad() auf oder wenn nötig jedes Mal, wenn die Ansicht in viewDidLayoutSubviews() angeordnet wird. (Wenn viewDidLoad() für dich zu früh ist, ist viewWillAppear() wahrscheinlich auch zu früh.)

    private func adjustScrollViewInsets() {
    
        // Dieser Ausschnitt fügt nur den unteren Teil des Tabellenansichts-Inhalts hinzu, aber du musst beide obere und untere Ränder anpassen, wenn du auch einen oberen Navigationsbalken berücksichtigen musst.
    
        var contentInset = tableView.contentInset
        if let windowInsets = view.window ?? UIApplication.shared.keyWindow?.safeAreaInsets {
            contentInset.bottom = windowInsets.bottom
        } else {
            contentInset.bottom = 0
        }
        tableView.contentInset = contentInset
    }

0voto

Vaibhav Nath Punkte 71

Getestet auf SWIFT 5.x

Nach mehrmaligem FEHLER im Beitrag:

  • Implementieren von tabBar-Delegaten
  • Festlegen des tabBarController-ViewControllers-Arrays
  • Implementieren des tabBar selectedIndex switch case

Kam endlich eine saubere Lösung in den Sinn...

  1. Erstelle eine neue UIViewController()-Klasse

  2. Weise sie dem entsprechenden tabBar-Element zu

  3. init() bestehenden View Controller aus Storyboard/XIB

  4. Pushe ohne Animation auf viewDidLoad()

    class FavouritesViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            guard let homeViewController = storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return }
            homeViewController.filterFavourites = true
            navigationController?.pushViewController(homeViewController, animated: false)
        }
    }

Um die Rückkehr-Gestennavigation zu verhindern, damit sie nicht bei Wischen am linken Rand zu einem leeren View Controller zurückkehrt

(OPTIONAL: Verberge auch die NavigationBar/Zurück-Schaltfläche, falls zutreffend in HomeViewController)

override func viewWillAppear(_ animated: Bool) {
    navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}

override func viewWillDisappear(_ animated: Bool) {
    navigationController?.interactivePopGestureRecognizer?.isEnabled = true
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X