Динамическое число 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
}