我创建了一个充当导航栏的集合视图,并将其设为基本视图控制器(TabBar.swift),它将出现在我的所有其他视图控制器上。它现在有3个单元格,单击每个单元格将把用户定向到其相应的视图控制器。 3个视图控制器分别是FirstScreen.swift,SecondScreen.swift和ThirdScreen.swift。这是基本视图控制器的代码:
TabBar.swift
struct OpenViewController {
var viewController: UIViewController
}
class TabBar: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
// Call all the elements
setupCollectionView()
view.backgroundColor = .white
}
let viewControllerList = [
OpenViewController(viewController: FirstScreen()),
OpenViewController(viewController: SecondScreen()),
OpenViewController(viewController: ThirdScreen()),
]
// Setup the collection veiw
func setupCollectionView() {
collectionView?.backgroundColor = .clear
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellID")
collectionView.showsHorizontalScrollIndicator = false
view.addSubview(collectionView)
addCollectionViewConstraints()
}
// Add constraints to the collection view
func addCollectionViewConstraints() {
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
collectionView.heightAnchor.constraint(equalTo: collectionView.widthAnchor, multiplier: 0.3).isActive = true
}
// The number of elements inside the collection view
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
// Adding the cells
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath)
// Customize the cells
cell.backgroundColor = .clear
cell.layer.cornerRadius = collectionView.contentSize.height / 2
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.black.cgColor
return cell
}
// The witdth and the height of the cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.height, height: collectionView.frame.height)
}
// Padding to the cells
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
}
// Selecting a cell and navigating to another view controller
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let openViewController = self.viewControllerList[indexPath.row]
self.present(openViewController.viewController, animated: true)
}
}
FirstScreen.swift
class FirstScreen: TabBar {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .yellow
}
}
SecondScreen.swift
class SecondScreen: TabBar {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}
ThirdScreen.swift
class ThirdScreen: TabBar {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
}
}
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let firstScreen = SecondScreen(collectionViewLayout: layout)
window?.rootViewController = firstScreen
return true
}
现在,当我运行此命令时,它会崩溃,原因是,例如,如果用户在FirstScreen.swift上,并且用户单击了第一个单元格,它将导致用户转到FirstScreen.swift,它将无法正常工作,有办法解决这个问题吗?希望在用户位于相应的视图控制器上时禁用单元格。
答案 0 :(得分:1)
问题是您正在尝试提供当前提供的vc,所以您可以这样做
var current:Int?
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard current != indexPath.row else { return }
let openViewController = self.viewControllerList[indexPath.row]
self.present(openViewController.viewController, animated: true)
current = indexPath.row
}
顺便说一句,我认为这最适合UISegmentedControl
答案 1 :(得分:0)
我现在无法自己尝试使用此代码,但是应该在collectionView(_ collectionView: UICollectionView, didSelectItemAt...)
中添加类似的内容:
let openViewController = self.viewControllerList[indexPath.row]
if type(of: self) != type(of: secondViewController) {
self.present(openViewController.viewController, animated: true)
}
最简单的方法是使用全局变量来跟踪选择了哪个索引,但这不是一种非常安全且不错的方法:P
答案 2 :(得分:0)
我复制并运行了您的代码,然后在这部分崩溃了
let viewControllerList = [
OpenViewController(viewController: FirstScreen()),
OpenViewController(viewController: SecondScreen()),
OpenViewController(viewController: ThirdScreen()),
]
我认为当您尝试在SecondScreen
中创建AppDelegate
时会出现死循环,此类的根TabBar
将再次创建SecondScreen
,然后它将一次又一次地重复此步骤...
您应在开始时将viewControllerList
设置为空,然后在viewDidLoad
的{{1}}中重新分配列表。
TabBar
这还将解决您遇到的崩溃(我想这是您遇到的崩溃)。因为在创建这些类时没有初始化collectionView的任何布局。就像在 override func viewDidLoad() {
super.viewDidLoad()
// Call all the elements
setupCollectionView()
view.backgroundColor = .white
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
viewControllerList = [
OpenViewController(viewController: FirstScreen(collectionViewLayout: layout)),
OpenViewController(viewController: SecondScreen(collectionViewLayout: layout)),
OpenViewController(viewController: ThirdScreen(collectionViewLayout: layout)),
]
}
var viewControllerList: [OpenViewController] = []
AppDelegate
希望它可以为您提供帮助。