Динамическое число ChildViewControllers для XLPagerTabStrip

Я использую XLPagerTabStrip создать приложение для чтения на основе категорий в Swift 4. Я узнал, что статическое число ViewControllers можно легко создать с помощью следующей функции.

override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { } 

Однако количество категорий в моем случае зависит от ответа сервера, который может меняться в зависимости от необходимости. Я попытался создать динамическое количество вкладок, создав контроллеры представления на основе названий категорий, которые я проанализировал из ответа json. Это метод, который я сделал удар и пробный период.

    override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
    var childrenVC = [UIViewController]()
    for eachCategory in postCategories {
            print(eachCategory)
        let newVC = self.storyboard?.instantiateViewController(withIdentifier: "FirstTVC") as? FirstTVC
        newVC?.childName = eachCategory.name
        childrenVC.append(newVC!)
        self.reloadPagerTabStripView()
        self.reloadInputViews()
}
    return childrenVC
}

Да, это не удалось. Как мне добиться динамического количества вкладок в этом случае? Если нет, я также открыт для любой другой альтернативы. Я закончил с ответом json, но застрял в этом шаге. Этот SO-ответ и Github Issue также не помогли.

3 ответа

У меня была точно такая же ситуация. Если вы извлекаете результаты с сервера асинхронно, как и вы, у вас будет сбой, поскольку xlpagertabstrip нужен хотя бы один дочерний viewcontroller. Решение, которое я нашел, - вернуть один фиктивный viewcontroller в начале приложения и после выборки данных с сервера в reloadPagerTabStripView.

В вашем родительском viewcontroller вы должны создать пустой массив ваших объектов, которые вы выбираете с сервера, например:

var menuItems = [MenuObject]()

Далее метод viewControllers(для pagerTabStripController ...) должен выглядеть следующим образом:

override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
    var children = [UIViewController]()
    if menuItems.count == 0 {
        let child = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DummyVC") as! DummyVC
        children.append(child)
        return children
    } else {
        let menuItemsUrls = menuItems.map{$0.url}
        for menuItem in menuItems {
            let child = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MainVC") as! TelegrafMainVC
            child.name = menuItem.name.uppercased
            child.url = menuItem.url
            children.append(child)
        }

        return children
    }
}

И после того, как вы получите данные с сервера, будь то использование URLSession, Alamofire или чего-то еще, в функции или замыкании, вы должны поместить что-то вроде:

self.menuItems = menuItems

 DispatchQueue.main.async {
       self.reloadPagerTabStripView()
 }

Скажите мне, если мне нужно что-то уточнить, но я верю, что этого будет достаточно, чтобы помочь вам. ура

Шаг 1: Сделайте это в вашем начальном viewcontroller,

class initialViewController: UIViewController {
     override func viewWillAppear(_ animated: Bool) {
          self.loadMainView(viewControllerArray: self.setMainViewTabParameters())
     }

 func setMainViewTabParameters() -> NSMutableArray {
      let viewControllerArray = NSMutableArray()
      var tabArray = ["Tab1", "Tab2", "Tab3", "Tab4", "Tab5", "Tab6", "Tab7"]

      var tabIndex = NSInteger()
      for item in tabArray {
           let tabString = tabArray[tabIndex]
           let tabview = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourTabControllerIdentifier") as! YourTabController
           tabview.tabHeadingTitle = tabString as NSString
           viewControllerArray.add(tabview)
           tabIndex = tabIndex + 1
      }
      return viewControllerArray
 }

 func loadMainView(viewControllerArray : NSMutableArray) -> Void {
      let mainView = self.storyboard?.instantiateViewController(withIdentifier: "YourMainControllerIdentifier") as! YourMainController
      mainView.viewControllerList = viewControllerArray
      self.navigationController?.pushViewController(mainView, animated: false)
 }
}

Шаг 2:

class YourMainController: ButtonBarPagerTabStripViewController {

     var viewControllerList = NSArray()
     var isReload = false

     //MARK: - PagerTabStripDataSource
     override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
          guard isReload else {
               return viewControllerList as! [UIViewController]
          }

          var childViewControllers = viewControllerList as! [UIViewController]

          for (index, _) in childViewControllers.enumerated(){
               let nElements = childViewControllers.count - index
               let n = (Int(arc4random()) % nElements) + index
               if n != index{
                    swap(&childViewControllers[index], &childViewControllers[n])
               }
          }
          let nItems = 1 + (arc4random() % 8)
          return Array(childViewControllers.prefix(Int(nItems)))
     }

     override func reloadPagerTabStripView() {
          isReload = true
          if arc4random() % 2 == 0 {
               pagerBehaviour = .progressive(skipIntermediateViewControllers: arc4random() % 2 == 0, elasticIndicatorLimit: arc4random() % 2 == 0 )
          } else {
               pagerBehaviour = .common(skipIntermediateViewControllers: arc4random() % 2 == 0)
          }
          super.reloadPagerTabStripView()
     }
}

Шаг 3: Ваш контроллер представления вкладок:

class YourTabController: UIViewController, IndicatorInfoProvider {
     var tabHeadingTitle = NSString()

     // MARK: - Top Tab Bar Method - IndicatorInfoProvider
     func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
          return IndicatorInfo(title: tabHeadingTitle as String)
     }
}

Попробуй это

override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
    var childrenVC: [UIViewController] = []

    for eachCategory in postCategories {
         let newVC = UIStoryboard(name: "Main (YOUR-STORYBOARD-NAME)", bundle: nil).instantiateViewController(withIdentifier: "FirstTVC") as? FirstTVC
         newVC?.childName = eachCategory.name
         childrenVC.append(newVC!)
    }
    return childrenVC
}
Другие вопросы по тегам